[Data structure] pure c language version singly linked list

Table of contents

1. The definition of linked list

2. Create a node

3. Plug in the linked list

4. Plug in the linked list

5. Delete the head of the linked list

6. Delete the tail of the linked list

7. Printing of the linked list

Eight, the destruction of the linked list

Nine, the lookup of the linked list 

10. Insert before a certain data in the linked list

11. Insert after a certain data in the linked list

12. Delete a certain position of the linked list

Thirteen, do not traverse the insertion node

14. Delete a node without traversing

Fifteen, the leader of the one-way linked list


1. The definition of linked list

typedef int SLTDataType;
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

In order to use the data type transformation in the future, here we use typedef to change the name of int. If we want to change other data types later, we can directly replace the int in the first line with the type you want.

Data in the structure stores data, and next stores the address of the next node.

We next create a node.

2. Create a node

SLTNode* BuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)//当内存申请失败了需要报错并停止运行
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->data = x;
	return newnode;
}

 We need to use a function of type SLTNode *, because we want to return the address of the created node.

So we can create a linked list and insert data into it

int main()
{
	SLTNode* plist = NULL;
	phead = BuyNode(1);
}

 phead represents the head node.

3. Plug in the linked list

void PushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode *newnode=BuyNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

It should be noted here that the second-level pointer is used. The reason for using the second-level pointer is because: we need to change the value of phead, so we must pass in the address of the plist.

4. Plug in the linked list

Here we need to discuss according to the situation: 1. The linked list is not empty. 2. The linked list is empty.

When the linked list is not empty, we only need to find the tail node, and then connect the new node.

But when the linked list is empty, we need to make the head pointer point to the new node (need to change the head pointer phead), so we still need to use the secondary pointer.

void SlistPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = BuyNode(x);
	if (*pphead == NULL)
		*pphead = newnode;
	else
	{
		//找到尾节点
		SLTNode* tail=*pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

5. Delete the head of the linked list

Here we set a del variable to store the node to be deleted. Every time we delete a node, we must free this node, otherwise there will be a risk of memory leaks.

void SListPopFront(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	SLTNode* del = *pphead;
	*pphead = (*pphead)->next;
	free(del);
	del = NULL;
}

6. Delete the tail of the linked list

void SListPopBack(SLTNode** pphead)
{
	assert(pphead);
	if (*pphead == NULL)
		return;
	//一个节点
	//多个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;

	}
	else
	{
		SLTNode* prev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}
		prev->next = NULL;
		free(tail);
		tail = NULL;
	}
}

Because the tail node needs to find the previous node of the node and set its next value to NULL, it needs to be discussed on a case-by-case basis.

7. Printing of the linked list

void SLTPrint(SLTNode* phead)
{
	if (phead = NULL)
		return;
	SLTNode* cur = phead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

Eight, the destruction of the linked list

Similar to the deletion above, the nodes of the linked list are all malloc'd, and it is a good habit to return the space of each malloc to the system to avoid resource waste.

void SLTistDestory(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

Finally, remember to point phead to NULL (that is, *pphead) to avoid the generation of wild pointers.

Nine, the lookup of the linked list 

Note that its return type is a pointer to a node, and returns NULL if no node is found.

SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{
	if (phead == NULL)
		return;
	SLTNode* cur=phead;
	while (cur)
	{
		if (cur->data == x)
			return cur;
		cur = cur->next;
	}
	return NULL;
}

10. Insert before a certain data in the linked list

We need to use the above find function to find the position (pos) before which element we want to insert. We need to find a node prev in pos, and then insert the new node between the prev node and the pos node.

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assrtt(pphead);
	assert(pos);
	if (*pphead == pos)
	{
		SListPopFront(x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
			prev = prev->next;
		SLTNode* newnode = BuyNode(x);
		newnode->next = pos;
		prev->next = newnode;
	}
}

11. Insert after a certain data in the linked list

Because a singly linked list can only be searched from front to back, we need to search down one by one from the head node to find the insertion position.

But if you want to insert data after a certain element, you only need to find one down.

void SListInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* next = pos->next;
	SLTNode* newnode = BuyNode(x);
	newnode->next = next;
	pos->next = newnode;

}

12. Delete a certain position of the linked list

It needs to be discussed according to the situation. I used two pointers here. When the linked list has only one element, there is no need for two pointers, so it needs to be discussed according to the situation.

void SListErase(SLTNode **pphead,SLTNode* pos)
{
	assert(pphead);
	assert(pos);
	SLTNode* prev=*pphead;
	if (pos == prev)
	{
		*pphead = pphead->next;
		free(pos);
		pos = NULL;
	}
	else
	{
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}

}

The idea is to find the previous (prev) of the position to be deleted, then change the next of prev to the next of pos, and finally release pos

  Given such a linked list, how do you insert a node before 3 nodes without traversing the linked list.

How do you delete the 3 nodes without traversing the linked list.

Thirteen, do not traverse the insertion node

To give an idea, insert a node after the 3 nodes:

and give it the value of 3 nodes:

 Finally, change the value of the three nodes to the value to be inserted:

You're done, paste the code:

void SListInsertBefore(SLTNode* pos,SLTDataType x)
{
	assert(pos);
	SLTNode *newnode=(SLTNode *)malloc(sizeof(SLTNode));
	newnode->data = pos->data;
	newnode->next = pos->next;
	pos->next = newnode;
}

14. Delete a node without traversing

The above idea: first assign the value of 4 nodes to 3 nodes.

 Then point the next of the 3-node to the next of the 4-node.

 Finally, destroy the 4 nodes.

Above code:

void SListErasePos(SLTNode* pos)
{
	assert(pos&&pos->next);
	SLTNode* next = pos->next;
	pos->data = next->data;
	pos->next = pos->next->next;
	free(next);
	next = NULL;//养成好习惯,吧malloc的空间释放掉
}

This method still has a flaw, that is, pos cannot point to the last node. The previous method does not have this trouble.

Don't worry too much about these methods, because the doubly linked list is the most practical in daily use.

Fifteen, the leader of the one-way linked list

When we write a linked list in pure C language, it is often applied to the secondary pointer where the head is deleted and the head is inserted. Here is a more reasonable way to deal with it:

Add a header node, and the head node does not store any data

How comfortable is this, for example, when the head is inserted, just add a node directly after the head node without judging whether it is an empty node, and when the head is deleted, directly let the head node point to the No. 2 node.

 

Guess you like

Origin blog.csdn.net/qq_64484137/article/details/126218802