The most detailed eight linked list structure and basic operation tutorial of singly linked list


insert image description here

1. What Xiaosheng wants to say

I am a freshman in the school, I hope the great gods can give more guidance. Last time we learned about the sequence table and its basic operations. Now let's take a look at the linked list. If you find it useful, don't forget to give Xiaosheng a note, and Xiaosheng will continue to update it.Come on, techie! ! !

2. Know the linked list

1. The basic concept of linked list

A linked list is a finite sequence of N data elements,Its length can be grown or shortened as required, like the previous sequence table, is a type of linear table.A sequential list is a sequential storage structure but a linked list is a chained storage structure.
insert image description here

Single listUse the node to store the data and the address of the next node, so the node is generally divided into multiple parts, namely the data field and the pointer field,The data field stores valid data, and the pointer field stores the address of the next node., while a singly linked list has only one pointer field, and a doubly linked list has two pointer fields.

2. Understand the difference and advantages and disadvantages of singly linked list and sequential list

These are two different storage structures. Let's talk about the difference first. The sequential table is a sequential storage structure.Its characteristic is that two elements that are logically adjacent to each other are also adjacent in physical position. But the linked list is different,The characteristic of the chain storage structure is that it does not require logically adjacent elements to be adjacent in physical location.. Because the chained storage structure can directly find the location of the next node through the pointer field in the node. insert image description here
The advantages and disadvantages of the sequence table:
1.advantage: You can directly access the required data through subscripts
2. Disadvantages:Cannot allocate memory as needed, you can only use malloc or realloc function for expansion, easy to achieve frequent expansion,It is easy to cause problems such as memory waste and data leakage.
Advantages and disadvantages of singly linked list:
1. Advantages:The length of the linked list can be increased or decreased by creating nodes according to actual needs, use memory to a greater extent.
2. Disadvantages:When inserting or deleting at the tail or at any position, the time complexity and space complexity are relatively large. Each time, the required position needs to be found by moving the pointer, which is less efficient than the sequential table lookup.

3. Know the eight types of linked lists

Before understanding the types of linked lists, we need to understand several characteristics of linked lists :
1. Unidirectional and Bidirectional
2. Leaded and Unleaded
3. Cyclic and Acyclic

We can combine methods, such as: one-way leading circular linked list, two-way non-leading non-circular linked list...
Xiaosheng draws a few pictures to let everyone know about it

~~One-way headed circular linked list

insert image description here
insert image description here

~~One-way headed acyclic linked list

insert image description here
insert image description here

~~One-way unleaded circular linked list

insert image description here

insert image description here

~~One-way unleaded acyclic linked list

insert image description here

insert image description here

~~ Bidirectional headed circular linked list

insert image description here
insert image description here

~~Doubly headed acyclic linked list

insert image description here
insert image description here

~~ Bidirectional circular linked list without head

insert image description here
insert image description here

~~ Bidirectional unleaded acyclic linked list

insert image description here
insert image description here

2. Basic operation of singly linked list

The singly linked list we refer to below is a singly unleaded acyclic linked list

1. Interface for basic operations (basic)

The singly linked list is similar to the sequential list. Addition, deletion, modification and checking are the basic operations on the singly linked list. Let's take a look at the basic interface first!

insert image description here

2. Structure definition of singly linked list

The nodes of a singly linked list are divided into two parts, the data field and the pointer field . So we can define a node with the following structure

typedef int SLTDataType;
typedef struct SListNode
{
    
    
	SLTDataType data;
	struct SListNode* pNext;
}SLTNODE;

3. Node Creation

Because the length of the linked list is subsequently increased, creating a node is to some extent the firstCreate a variable of the structure pointer type, initialize it, and finally return the variable, we can analyze directly through the code. Let's first look at the creation of a linked list with head nodes

SLTNODE* CreateNode(SLTDataType val)
{
    
    
	SLTNODE* pNew = (SLTNODE*)malloc(sizeof(SLTNODE));
	pNew->data = val;
	pNew->pNext = NULL;
	return pNew;
}

4. Distinguish the transmission of the first-level pointer and the second-level pointer

If you want to change the head pointer of the linked list, you need to pass the second-level pointer. Changing the head pointer cannot pass the first-level pointer because the transfer process is the process of copying, which is equivalent to copying the head pointer. The change of the formal parameter will not affect the actual parameter. Therefore, to change the head pointer of the linked list, it is necessary to transfer the secondary pointer.

5. Insertion of a singly linked list

~~The header of the singly linked list

Because we emphasized earlier,The singly linked list we operate on has no head node, so the head plug is very convenient. As for how to operate the singly linked list with the head node, it is also very simple. I believe that the great gods can write it by themselves.

//因为要改变头指针所以我们要传送头指针的地址,即二级结构体指针变量
 void SListPushFront(SLTNODE** ppHead, SLTDataType val)
{
    
    
	
	SLTNODE* pNew  = CreateNode(val);
	pNew->pNext = *ppHead;
	*ppHead = pNew;
}

~~Tail insertion of a singly linked list

When inserting the tail, we need to consider whether the singly linked list is empty , because if it is empty, we need to point the head pointer to the new node.

void SListPushBack(SLTNODE** ppHead, SLTDataType val)
{
    
    
	SLTNODE* pNew = CreateNode(val);
	//判断链表是否为空,若为空则将头指针指向新结点
	if (*ppHead == NULL)
	{
    
    
		*ppHead = pNew;

	}
	else
	{
    
    
		SLTNODE* pTail = *ppHead;
		//通过循环让指针找到尾部
		while (pTail->pNext != NULL)
		{
    
    
			pTail = pTail->pNext;
		}
		pTail->pNext = pNew;
	}
	
}

I wonder if the gods have noticed that the condition of our loop is pTail->pNext != NULL, can it be changed to pTail != NULL? At first glance, it seems that there is no problem, but is there really no problem? Let's think about it~

Let's first look at the correct loop condition pTail->pNext != NULL

For convenience, we use pHead instead of *ppHead in the figureinsert image description hereAt this time, pTail->pNext != NULL is established, and the pTail pointer is moved backward insert image description here. At this time, pTail->pNext != NULL is established, and the pTail pointer is moved backward
insert image description here
. Note that there is no node behind at this time, then the node pointed to by pTail at this time is inside The pointer field stores a null pointer, that is, pTail->pNext is empty, and pTail just points to the last node . Let's take a look at the case where the loop condition is pTail != NULL.
insert image description here
At this time, pTail != NULL is established. When the pTail pointer is moved backward,
insert image description here
pTail != NULL is still established. When the pTail pointer is moved backward,
insert image description here
pTail != NULL is still established. After the pTail pointer shift
insert image description here
From the above we can find that when the condition of pTail != NULL is executed, it will not stop when pTail points to the tail node , so the loop condition is wrong

~~Insert at the specified position of the singly linked list

~~ insert before pos position

Here we have two cases,pos is the first node and pos is not the first node. If pos is 1, it is equivalent to head insertion. If pos is not 1, use two pointers to find the previous node of pos and pos through a loop.
insert image description here
insert image description here

void SListInsert(SLTNODE** ppHead, SLTNODE* pos, SLTDataType val)
{
    
    
	//1.pos是第一个结点,在pos之前插入相当于头插
	if (*ppHead == pos)
	{
    
    
		SListPushFront(ppHead, val);
	}
	//2.pos不是第一个结点
	SLTNODE* pPrev = NULL;
	SLTNODE* pMove = *ppHead;
	while (pMove != pos)
	{
    
    
		pPrev = pMove;
		pMove = pMove->pNext;
	}
	SLTNODE* pNew = CreateNode(val);
	pPrev->pNext = pNew;
	pNew->pNext = pos;
}

Here we use two pointers, we can passa pointerIs it directly implemented? let's try

void SListInsert(SLTNODE** ppHead, SLTNODE* pos, SLTDataType val)
{
    
    
	if (*ppHead == pos)
	{
    
    
		SListPushFront(ppHead, val);
	}
	 SLTNODE* pPrev = *ppHead;
	 while(pPrev->pNext != pos)
	 {
    
    
		  pPrev = pPrev->pNext;
	 }
	 SLTNODE* pNew = CreateNode(SLTDataType val);
	 pPrev->pNext = pNew;
	 pNew->pNext = pos;
	
	SLTNODE* pNew = CreateNode(val);
	pPrev->pNext = pNew;
	pNew->pNext = pos;
}

Obviously it can,Because the pos pointer has been determined, it is not necessary to search for the tail like the previous tail insertion, but only need to find the node before pos.
insert image description here
insert image description here

~~ insert after pos position

A singly linked list can find the next node through the previous node, but cannot find the previous node through the latter node. Therefore, when inserting after the pos position, there is no need to find the node through the circular movement of the pointer when inserting before the pos position, because the next node can be found directly through pos

 void SListInsertAfter(SLTNODE * pos, SLTDataType val)
{
    
    
	assert(pos);
	SLTNODE* pNew = CreateNode(val);
	pNew->pNext = pos->pNext;
	pos->pNext = pNew;
}

6. Deletion of a singly linked list

Deletion and insertion are similar to a certain extent, and can be compared by analogy~~~

~~Delete the head of the singly linked list

Release the original first node and move the head pointer to the next nodeinsert image description here >insert image description here

void SListPopFront(SLTNODE** ppHead)
{
    
    
	assert(*pHead);
	SLTNODE* next =  (*ppHead)->pNext;
	free(*ppHead);
	*ppHead = next;

}

~~Tail deletion of singly linked list

There are three cases to consider when tail deletion ,Whether the linked list is empty, the linked list has only one node and the linked list has multiple nodes

void SListPopBack(SLTNODE** ppHead)
{
    
    
	//1.链表为空
	assert(*ppHead);
	//2.只有一个结点
	if ((*ppHead)->pNext == NULL)
	{
    
    
		free(*ppHead);
		*ppHead = NULL;
	}
	//3.有两个及以上的结点
	SLTNODE* pPrev = NULL;
	SLTNODE* pTail = *ppHead;
	while (pTail->pNext != NULL)
	{
    
    
		pPrev = pTail;
		pTail = pTail->pNext;
	}
	free(pTail);
	pPrev->pNext = NULL;
}

~~Delete the specified position of the singly linked list

When pos is equal to the head pointer, it is equivalent to the head deletion of the linked list. We can directly call the head deletion function SListPopFront() written before.

void SListErase(SLTNODE** ppHead,SLTNODE* pos)
{
    
    
	if (pos == *ppHead)
	{
    
    
		SListPopFront(*ppHead);
	}
	else
	{
    
    
		SLTNODE* pPrev = *ppHead;
		while (pPrev->pNext != pos)
		{
    
    
			pPrev = pPrev->pNext;
		}
		pPrev->pNext = pos->pNext;
		free(pPrev);
	}
}

7. Search of singly linked list

Find the node that stores the corresponding data in the data field by moving the pointer continuously and return the pointer

SLTNODE* SListFind(SLTNODE* pHead,SLTDataType val)
{
    
    
	SLTNODE* pMove = pHead;
	while (pMove != NULL) //while(pMove)
	{
    
    
		if (pMove->data == val)
		{
    
    
			return pMove;
		}
	}
	return NULL;
}

8. Destruction of a singly linked list

The destruction operation should be the easiest, Xiaosheng will not be wordy, I believe the gods will understand it at a glance

 void SListDestroy(SLTNODE** pphead)
{
    
    
	SLTNODE* pMove = *pphead;
	while (pMove !=NULL)
	{
    
    
		SLTNODE* next = pMove->pNext;
		free(pMove);
		pMove = next;
	}

	*pphead = NULL;
}

4. Conclusion

I am very grateful to the great gods for being able to see this. Xiaosheng would like to thank everyone here. Xiaosheng took everyone to a rough understanding of the structure of eight linked lists and the basic operations of a single linked list. It is not easy to code words, and it is not easy to be original. ! ! In the next article, we will enter the doubly linked list and circular linked list, come on technicians (don't forget to like and follow) ~~~
insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/qq_59955115/article/details/123588720