PrefaceThis paper uses a very important idea--the idea of generic programming; If you are unfamiliar with generics, you can search for relevant materials by yourself (void *, such as Memcpy,memmove,qsort,memset). At the end of this article will provide a demo program attachment, the demo program is written in C99 Standard, LINUX-GCC under the debugging, VC6 may have errors. In the illustration in this article,
Red Solid LineRepresents the place to add,
Black Dashed lineIndicates the place to break,
solid black Lineremain intact. This article is designed as the simplest non-circular single-linked list.
comparing arrays to linked lists
|
Array |
Linked list |
Advantages |
Fast access speed and ease of operation |
Unlimited size Insert Delete Easy to implement space without continuous |
Disadvantages |
Inserting and deleting operations is not easy to implement requires continuous space storage array elements require the same type |
Slow access speed and complex operation |
By comparison, we can find that the advantages of the array are just the disadvantages of the list, and the disadvantage of the list is the advantage of the array.
categories of linked lists
single linked listEach node has 1 pointer fields, pointing to successor (next)
Double Linked listEach node has 2 pointer fields, one pointing to the precursor (previous), and one pointing to the successor (next)
Circular link ListEnd-to-end, Tail->next = head; Can find all the other nodes through any node
non-circular linked listTail->next = NULL, and all nodes can be found through head.
linked list data structure
typedef
structnode{//Node structure
void*data;
structNode *next;
} node;
typedef
struct{//Linked list structure
structNode *head;
structNode *tail;
LongLen
} List;
common linked list algorithmInitialization
voidList_init (List *list); Destroyed
voidList_destroy (List *list,
void(*destroy) (
void*)); Insert
voidList_insert (List *list,
void*data); Head Insertion method
voidList_insert_at_head (List *list,
void*data); With interpolation method
void
List_insert_at_index (List *list,
void*data); Tail interpolation method
void
List_insert_at_tail (List *list,
void*data,
LongIDX); Delete
void*list_delete (List *list,
void*key,
int(*compare) (
Const
void*,
const void*)); Search
void*list_search (List *list,
void*key,
int(*compare) (
const void*,
const void*)); Sort
void*list_sort (List *list,
void*key,
int(*compare) (
const void*,
const void*)); Traverse
voidList_traverse (List *list,
void(*handle) (
void*)); Reverse
voidList_reverse (List *list); Request length
LongGet_lenth (List *list); Get linked list node
void*list_get_element (List *list,
Longindex); Judging empty linked list
BOOLIs_empty (List *list);
The detailed and realization of each algorithmThe linked list structure is known as follows
typedef
struct{//Linked list structure
structNode *head;
structNode *tail;
LongLen
}
List; The linked list has 3 attributes, head-pointer heads, tail-pointer tail, and a linked-list-length Len; First, define a linked list,
ListList At this point the list structure is as follows:
the initialization of a linked listWhen a linked list is just established, it does not contain any valid data, that is, does not contain a valid node. So the head and tail pointers tail are not pointing, that is, to null, at which time the list length is 0. That is, the linked list structure is implemented as follows
voidList_init (List *list)
{
List->head = NULL;
List->tail = NULL;
List->len = 0;
} The list that has just been initialized is an empty list, and the head pointer of the empty list must be null, which can be used as the basis for judging the empty list, thus realizing
procedures for judging empty lists#
include<stdbool.h>
BOOLIs_empty (List *list)
{
return(List->head = = NULL);
}
inserting a linked list nodeAfter the list has been initialized, it is possible to perform various operations (such as inserting and deleting nodes, seeking lengths, destroying linked lists, etc.), and explaining the operation method of the list insertion, the insertion node needs to be discussed in 2 different situations:
when the linked list is empty, the first node inserted (the first node);
inserts a node on a non-empty list.
1. The first caseThe following illustration shows that there is only one node A at this point, where Node A is both the first node (so head points to Node A), and the tail node (so tail also points to Node A, and A->next = NULL), while the list length is +1 (in the Insert program, Len always appears + + status, not described below). program implementation (assuming n is the node to be inserted)
structNode *new;
List->head = new;
List->tail = new;
New->next = NULL;
list->len++;
2. The second caseThe second case is divided into 3 cases, according to the insertion position of the new node, divided into 1. In the head insertion, head interpolation: List_insert_at_head (...) ; 2. In the tail plug, tail interpolation method: List_insert_at_tail (...) ; 3. Insert at index node, insert method: List_insert_at_index (...).
2.1, head interpolation methodAnalysis of the legend shows that there is already a list (left), list->head = A; now to insert a node N at the head, you need to disconnect the head from a, make N->next = A, and then List->head = N (The two steps are not interchangeable in order, You can think about why. )。 The program is implemented as follows:
structNode *
New;
New->next = list->head->next;
List->head =
New;
list->len++;
2.2, tail interpolation method
The analysis legend shows that there is already a list (left), list->tail = Z; now to insert a node N at tail, you need to disconnect tail from Z, so z->next = N; (that is, List->tail->next = n; Then List->tail = N (These two steps can be reversed in order.) Think about why. ), and then make N->next = NULL. The program is implemented as follows:
structNode *
New;
List->tail->next =
New;
List->tail =
New;
New->next = NULL;
list->len++;
2.3, with interpolation methodAnalysis of the legend shows that there is already a list (left), a->next= B; now to insert a node n at a, you need to disconnect A and B, make n->next = B; (i.e. N->next = a->next;) and then make A->next = N (These two steps can be reversed in order.) Think about why. )。 The interpolation method is not necessarily inserted at the a node in the diagram because of the insertion position, possibly B, C, d, or even Z. So here we need to find the insertion position by a user-given index value with List->head. The code is implemented as follows:
Static
structNode *make_node (
void*data)//package The data passed by the user as a linked list node
{
structNode *n;
n = malloc (
sizeof(
structnode));
ASSERT (n! = NULL);
N->next = NULL;
N->data = data;
returnN
}
voidList_insert_at_head (List *list,
void*data)//Head Insert method
{
structNode *n;
n = make_node (data);
if(List->head = = NULL) {//If it is an empty list
List->head = n;
List->tail = n;
}
Else{//If not a non-empty linked list
N->next = list->head;
List->head = n;
}
list->len++;
}
void