Linked List, C linked list
A linked list is a struct.
Therefore, to implement a linked list, you must use the linked list struct and node struct.
Node struct
Typedef struct node {// The struct int a of the node; struct node * next; // struct node * previous;} node, * pnode;
In this example, a is the attribute attached to a node. It may not only have one int type variable, but also have char name [15] and other data.
For convenience, use the typedef keyword to rename the node struct.
The linked list structure is similar
1 typedef struct {// structure of the linked list 2 pnode head; 3 pnode last; 4 int lenth; 5} list, * plist;
In this node, you can add additional attributes of the linked list, such as the length of the linked list.
In some books, instead of defining the linked list struct, it is feasible to replace the global variable head with only one node type pointer. However, if we want to create multiple linked lists, this will not be good. In addition, a linked list can have multiple attributes. If it is written as a struct type, it is obviously more beneficial for attribute expression.
For a linked list, its length is variable. This is one of the main reasons for using a linked list instead of an array. The malloc function is used to increase the length at will, and the prototype of the malloc function is:
Void * malloc (long NumBytes );
First, the function of the malloc function is to apply for a piece of memory from the system. We can see that the malloc function has only one parameter, long NumByte. This long parameter indicates the memory size applied to the system. Because different systems allocate different memory sizes for different types of variables, we generally use sizeof to calculate the size. Malloc returns a null pointer, so we need to forcibly convert it. In addition, the memory system allocated using the malloc function will not be automatically released, so we need to release the memory at the end of the program and use the free function. The prototype of the free function is void free (void * FirstByte). Its parameter is the address of the slave to release the memory, that is, the pointer to the memory.
Linked lists are essentially pointer applications. The connection between a node and a node is represented by the pointer variable of the node struct defined in the node. In this example, it is the next variable.
For a one-way linked list, there is only one pointer variable in the node. This pointer variable stores the address of the next node. By referencing this pointer variable, you can obtain the content of the next node. We can think of the pointer variable as an iron chain connecting two nodes. Then multiple nodes are connected to each other to form a chain. This is the linked list. For this chain, we can only access and use it at the beginning and end, so we wrap it up, the packaging bag of the chain should expose the head and tail of the chain. This is the head and last pointer. The length of the chain should also be indicated on the bag, that is, the length variable.
For a bidirectional linked list, there are two pointer variables in the node. In this example, the previous variable is commented out. The principle is to store the pointer of the previous node in the previous variable, we can not only traverse the head over-chain table to the last table, but also traverse the head through the last table. In short, this linked list is bidirectional.
The basic operation of the linked list is add, delete, modify, and query.
First, add
Void add (plist p) {int I = 0, j = 0, k = 0; pnode news = (pnode) malloc (sizeof (node )); // remember to release scanf ("% d", & news-> a); news-> next = NULL; // assign a value to news if (0 = p-> lenth) {// at this time, the linked list is empty p-> head = news; // The head pointer of the linked list points to the address p-> last of the new node news; // The linked list is empty at this time, so the new node news is also the last node p-> lenth = p-> lenth + 1; // news has been added to the linked list, length of the linked list plus one} else {// if the length of the linked list is not empty, p-> last-> next = news; // The End Node of the linked list points to the new node news p-> head = news; // The end pointer of the linked list moves back to the new node news, at this time, news is the last node p-> lenth ++; // The length of the linked list plus one}
//p->lenth++;
}
In this example, we first apply for a piece of memory from the system through the malloc function to store new nodes and initialize the nodes. In this example, the initialization statement for the node is only: scanf ("% d", & news-> a); but in actual application, because the data field of a node has multiple data records, more initialization statements are available, and the refresh of the buffer zone must be noted in multiple initialization statements. Here is an example: scanf ("% d", & a); gets (c); here, after the input is complete, the value of c is the carriage return. This is because after entering scanf, we press enter to generate a carriage return. This carriage return remains in the buffer zone and is read by the gets function.
To solve this problem, one method is to write: scanf ("% d", & a); getchar (); gets (c); the carriage return is eaten with getchar.
Another way is to use the flush () function to refresh the buffer. In this way, the write speed will be relatively high, but the height will not go anywhere.
Another way is to write: scanf ("% d % * c", & a); gets (c ); here, % * c is used to read a character in scanf and discard it. In the scanf function, for example, scanf ("% c", & c); this adds a space before "%". It skips all white spaces and reads the first non-white space character, assign value to variable c
We recommend that you record the effects of each input function. For example, if the scanf function reads % s, it stops reading the function when it encounters a space. The gets function reads a string and discards the carriage return, the puts function automatically adds a carriage return. In this way, you can write more flexible code.
After initialization, we need to determine whether the length of the linked list is null. If the linked list is empty, the new node is the first node and the last node. Both head and last point to it. If the linked list is not an empty table, we will add this node to the back of the linked list. To add a linked list, the next pointer of the last node of the original linked list is directed to the newly added node, and the last pointer of the linked list is directed to the new node, the new node becomes the new last node. In some posts, the headers and tails are the same in principle.
After completing the preceding operations, add the length of the linked list to one.
Then delete the file.
1 void deletes (plist p, int n) // delete node 2 {3 int I = 0, j = 0, k = 0; 4 pnode iterator; 5 iterator = p-> head; 6 for (I = 1; I <n; I ++) {// from the traversal Link Table to the previous node to be deleted, 7 iterator = iterator-> next; 8} 9 iterator-> next = iterator-> next; 10 free (iterator-> next); 11 p-> lenth --; 12}
The deletion principle is that the next pointer of the previous node to be deleted points to the next node of the node to be deleted. In this way, the node to be deleted is deleted from the linked list. Because we use the memory applied by the malloc function to increase the function, we need to use free to release the memory of the node to be deleted during the deletion process. Do not forget to reduce the length of the linked list by one.
In this Code, we use an iterator variable to store intermediate nodes and iterate through the entire linked list.
Check
Void search (plist p, int n) {// query the node int I = 0, j = 0, k = 0 at index n; pnode iterator; iterator = p-> head; if (0 = p-> lenth) {printf ("error, the length of the linked list is zero"); return ;}for (I = 1; I <n; I ++) {iterator = iterator-> next;} printf ("the value of the node at index n is: % d", iterator-> );} void search2 (plist p, int n) {// the index value of the node whose query value is n: int I = 0, j = 0, k = 0; pnode iterator; iterator = p-> head; for (I = 0; I <p-> lenth; I ++) {if (n = iterator->) printf ("Node % d is one of the requested nodes", I + 1); iterator = iterator-> next ;}}
There is no difficulty in the query operation, so I will not talk about it much.
As for this, it is similar to the above functions and will not be written.
Finally, the most important thing is to destroy the entire linked list.
Void destroy (plist p) {int I = 0; pnode iterator = p-> head; // The iterator points to the first node of the linked list if (0 = p-> lenth) return; // if the linked list is empty, this returns, no operation is performed for (I = 0; I <p-> lenth; I ++) {p-> head = p-> head-> next; // point the head to the second node free (iterator); iterator = p-> head ;}}
Traverse the entire linked list and release its nodes one by one. Then call this function at the end of the main function.
This is the linked list.