We have learned the sequence table before. The sequence table refers to the arrangement one by one in the physical memory, and the addresses of each element in the sequence table are closely connected. This kind of table deletion and insertion is very troublesome because we have to move all elements back. The worst time complexity is O(n). When dealing with a large number of data with variable order and number at any time, we use the linked list mentioned today
Basic definition of linked list
A linked list is a list in which the addresses of each node in physical memory are discontinuous. They are connected by pointers. There is no more talk about the basic definition of a linked list here
We only need to know that the linked list is composed of nodes and the whole linked list is marked by a header pointer.
What we want to study today is the sequential list of linked list, that is, the pointer field of a node points to the address of the next node
Data type of node
typedef int ElemType; /*The head node of the linked list does not store data, but only serves as a sign to find other nodes*/ struct Node { ElemType data; struct Node* next; }; //Node initialization typedef struct Node Node; typedef struct Node* LinkList;
Data is a data field that stores data. Next is the pointer field, pointing to the address of the next node
Summary of ADT method for sequence table
void SLTInite(LinkList head);//Initialize linked list void SLTPrint(LinkList head);//Traversal print linked list void SLTPushBack(LinkList head, int e);//Tail interpolation void SLTPushFront(LinkList head, int e);//Head insertion void SLTPopBack(LinkList head);//Tail deletion void SLTPopFront(LinkList head);//First deletion method void SLTGletElem(LinkList head, int pos, int* e); //Assign the value of the ith node to e void SLTInsert(LinkList head, int pos, int e); //Insert the e node at pos void SLTEraese(LinkList head, int pos);//Delete pos position void CreatWholeListFronthead(LinkList* head, int n);//Directly create a linked list with n nodes with a header. The header node form is created earlier, and the header insertion method is used to create the linked list void CreatWholeListBackhead(LinkList* head, int n);//Create a linked list of n nodes with header. The pointer of the head node is created in front, and the tail interpolation method is used to create the linked list void ClearList(LinkList* head); //Delete the entire table corresponding to the previous entire table creation
Initialization of sequence table
Sequence table has two forms of initialization: node initialization and pointer initialization
Node initialization is that I created the header node earlier, so we will use node initialization
void SLTInite(LinkList head)//Initialize linked list { head->data = 0; head->next = NULL; }
Pointer initialization is that we created a pointer to the node. It should have stored the address of the head node, but it has just been created and temporarily stored NULL, so we call this initialization pointer initialization
LinkList head = NULL; //Null value is assigned when pointer is created to prevent wild pointer
This initialization is generally used for the overall initialization of actual development. When initializing the function, you need to create a node first and let the head pointer point to it, so that the address of the head node is stored in the child head
void STLInite(LinkList* phead) { Node* NewNode = (Node*)malloc(sizeof(Node)); *phead = NewNode; *(phead)->next = NULL; }
Note that what we pass here is the head pointer phead, because what we want to change is the head value. Only by passing the head address can we change the head value;
Creation of new nodes in linked list
LinkList CreatNode(int e) { Node* NewNode = (Node*)malloc(sizeof(Node)); NewNode->data = e; NewNode->next = NULL; return NewNode; }
e here represents the value I need to assign to the node data field when creating
Traversal of linked list
void SLTPrint(LinkList head)//Traversal print linked list { LinkList p = head->next; while (p != NULL) { printf("%d->" ,p->data); p = p->next; } printf("NULL\n"); }
In this way, there will be a small arrow between each sub node, which is very nice to print
(funny)
Tail interpolation
void SLTPushBack(LinkList head, int e)//Tail interpolation { LinkList NewNode = CreatNode(e); LinkList p = head; while (p->next != NULL) { p = p->next; }//Tail pointer found p->next = NewNode; }
Tail interpolation requires two steps
1, Tail node found
2, Insert the newly created node
The flag of the tail node is p - > next = = null, and the pointer field points to null value, so we only need to make the pointer field of the tail node point to the new node, and then make the pointer field of the new node point to null value.
The key to finding the tail node is p = P - > next, which is equivalent to pointing to the next node. In this way, the node pushes the node and goes all the way back.
First interpolation
void SLTPushFront(LinkList head, int e)//Head insertion { LinkList NewNode = CreatNode(e); NewNode->next = head->next; head->next = NewNode; }
The first insertion is better understood. You only need to put the newly created node behind the head node, and let the next of the head node point to it, and its next point to the point that the head node once pointed to
The relationship between these two steps is that we need to modify the pointer field of newnode first, because if we modify it later, the pointer field of the header node has changed.
Tail deletion
void SLTPopBack(LinkList head)//Tail deletion { LinkList p = head; LinkList Nextp = p->next; if (head->next == NULL) { printf("ERROR,List Empty\n"); } else { while (Nextp->next != NULL) { p = p->next; Nextp = p->next; }//We found the last one. Nextp is the last one. p is the penultimate one. We want to delete nextp p->next = NULL; free(Nextp); } }
All delete interface functions have a major premise, that is, my linked list must have nodes before it can be deleted. We must first judge whether the linked list is empty
After confirming that the linked list is not empty, we will start the deletion operation. We divide the deletion operation into two steps, namely
Find the previous of the tail node.
Release the tail node and modify the pointer field
To complete these two steps, we need to create a pointer so that it always points to the next bit of the pointer we want to keep. Then make it go step by step through the while loop. When the pointer field of the next pointer is empty, we find the end to be deleted. Just modify it normally and release the node.
Core: two pointers
Head deletion
void SLTPopFront(LinkList head)//First deletion method { if (head->next == NULL) { printf("ERROR, List Empty\n"); } else { LinkList Nextp = head->next; head->next = Nextp->next; free(Nextp); } }
Like the tail deletion method, after ensuring that the table is not empty, we first receive the first node with a temporary pointer, then modify the pointer field of the header node to point to the second node, and finally free the first node released
Linked list value
void SLTGletElem(LinkList head, int pos, int* e) //Assign the value of the ith node to e { LinkList p = head->next;//Get the address of the first node int flag = 1; //Counter while (p != NULL && flag < pos) { p = p->next; flag++; } /*There are two situations after ending the 0while loop 1,p NULL first In this case, our p points to a null pointer At this time, it's better than flag If flag is less than or equal to pos That means I haven't seen your pos after I've finished this watch, which means that the value of pos is wrong*/ /*2,p NULL not reached. falg equals pos first That means we found it*/ if (p == NULL || flag > pos) printf("ERROR,Wrong position\n"); else { *e = p->data; printf("RIGHT,Get elem finish\n"); } }
We need to define a flag variable, which is used as a counter to judge which node of the linked list is currently.
There are two steps to complete the value taking operation
Find the corresponding node
Take value
The previous while loop is the process of finding nodes, in which P= Null indicates that the linked list has not been completed, and flag < POS indicates that the corresponding node has not been found.
In this way, there are two ways to jump out of the while loop. One is to finish the linked list. In this case, the given position is large and higher than the total length of our table. The second situation is that the flag is equal to pos before the table is finished. This situation indicates that it has been found.
Next, we have to make a judgment on whether to find it. If P==NULL, then he is finished and reports an error!
The second statement, false > pos, is basically impossible in practice. It is just used as the inversion of the while judgment condition to ensure that the following flag must be equal to pos
Insert anywhere in the linked list
void SLTInsert(LinkList head, int pos,int e) //Insert the e node at pos { Node* NewNode = CreatNode(e); int flag = 1; LinkList p = head->next; while (p != NULL && flag < pos-1) { p = p->next; flag++; } if (p == NULL || flag > pos-1) printf("ERROR,Wrong Position\n"); else { NewNode->next = p->next; p->next = NewNode; }
This needs to go through the same cycle judgment system with the same value. Its core purpose is to find the previous element of the pos position and complete the node insertion by using the first interpolation step we talked about earlier.
Delete anywhere in the linked list
void SLTEraese(LinkList head, int pos)//Delete pos position { LinkList p = head->next; int flag = 1; while (p != NULL && flag < pos-1) { p = p->next; flag++; }//Get the previous pointer I want to delete if (p == NULL || flag > pos-1) printf("ERROR, Wrong Position\n"); else { LinkList Nextp = p->next; p->next = Nextp->next; free(Nextp); } }
As before, after the loop judgment system, find the previous one I want to delete. Using the header deletion method mentioned above, create a temporary pointer to the elements to be deleted, adjust the order relationship, and finally complete the deletion.
Whole table initialization
void CreatWholeListFronthead(LinkList* head, int n)//Directly create a linked list with n nodes with a header. The header node form is created earlier, and the header insertion method is used to create the linked list { /*Why is the second level pointer of head passed*/ /*Because we first import a pointer to the next node one by one. If we want to modify this pointer, we can only import its address and change its value by dereferencing*/ *head = (Node*)malloc(sizeof(Node)); //The header node is created //Head is a pointer to LinkList, that is, the address of the linked list node, so head is a pointer to the address of the linked list node, so * head points to the linked list node (*head)->next = NULL; int flag; for (flag = 1; flag <= n; flag++)//Multiple head interpolation { LinkList p = (LinkList)malloc(sizeof(Node)); /*Why not directly create variables in the form of nodes here?*/ /*Because it's easier to call with a pointer*/ int t; scanf_s("%d", &t); p->data = t; p->next = (*head)->next; (*head)->next = p; } }
We use the header interpolation method to create the linked list of the whole table. Since the header node is not initialized, we need to initialize the header node first, and then perform the header interpolation bit by bit.
Linked list initialization tail interpolation
void CreatWholeListBackhead(LinkList* head, int n)//Create a linked list of n nodes with header. The pointer of the head node is created in front, and the tail interpolation method is used to create the linked list { *head = (LinkList)malloc(sizeof(Node)); (*head)->next = NULL; //Header node initialization completed int flag; LinkList fp = *head;//Head node firstpoint LinkList lp;//Tail node lastpoint lp = fp; for (flag=1; flag <= n; flag++) { /*int t; scanf_s("%d", &t); SLTPushBack(*head, t); Interface function form*/ int t; scanf_s("%d", &t); LinkList NewNode = (LinkList)malloc(sizeof(Node)); NewNode->data = t; NewNode->next = NULL; //while (fp->next != NULL) //{ // fp = fp->next; //}//The head node is the only flag of the linked list lp->next = NewNode; //The next bit of the tail node points to my newly generated node lp = NewNode;//At this time, our newly generated node becomes a new tail node after tail insertion /*In this way, you don't have to cycle while to the end every time to save time*/ } }
It's almost the same as before. It doesn't explain QWQ
Deletion of the whole linked list
void ClearList(LinkList* head) //Delete the entire table corresponding to the previous entire table creation { LinkList p, temp; p = (*head)->next; //Get the first node first if (p!=NULL ) { while (p->next != NULL) { temp = p; p = p->next; free(temp); } (*head)->next = NULL; printf("The entire table has been deleted\n"); } else { printf("Table is empty\n"); } }
Deleting the linked list is the last step of the whole operation. We delete the head node in the same way as before. After deletion, the original second position becomes the head node. Repeat the above process. Finally, we clear the address pointed to by the head pointer to complete the deletion of the whole table
Here is the whole interface function of the one-way linked list. Thank you for reading.
Reference textbook
Data structure by Yan Weimin