Read the big talk data structure carefully and win 45 points EP3 with you

Posted by mjlogan on Wed, 08 Sep 2021 03:43:51 +0200

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

Topics: Algorithm data structure linked list