[Data structure] Single linked list | Detailed explanation

Advantages and disadvantages of linear table sequential storage structure

Advantages of sequence table

  • There is no need to add additional storage space to express the logical relationship between intermediate elements;
  • Because it is stored in the form of an array, elements at any position in the table can be quickly accessed.

Disadvantages of sequence table

  • Insertion and deletion operations require moving a large number of elements, and the time complexity is O(N);
  • When the length of the linear table changes greatly, it is difficult to determine the capacity of the storage space;
  • Causes "fragmentation" of storage space.

Solutions to insufficient sequential storage structures

In fact, the biggest disadvantage of the sequential table is that a large number of elements need to be moved during insertion and deletion, which obviously takes a lot of time because the storage locations of two adjacent elements also have neighbor relationships. Their numbers are 1, 2, 3,..., n. Their positions in the memory are also next to each other. There is no gap in the middle, so of course it cannot be quickly intervened. After deletion, there will be a gap in the middle, which naturally needs to be filled. .

In this case, we have to leave enough room for adjacent elements anyway, so we simply don't consider the adjacent positions of all elements, just go wherever there is space, and just let each element know the location of its next element. Where is the position, so that when we are in the first element, we know the position (memory address) of the second element and find it; when we are in the second element, we know the position (memory address) of the third element ) and find it. In this way, we can find all elements by traversing.

In fact, this idea is also the idea of ​​linked list storage, and this article focuses on the singly linked list in the linked list.

Linear list chain storage structure definition

In the chain structure, in addition to storing the data element information, the storage address of its subsequent elements is also stored.

Data domain: The domain that stores data element information is called the data domain;

Pointer field: The field that stores the immediate successor position is called the pointer field.

The information stored in the pointer field is called a pointer or chain. The data field and pointer field information form a storage image of data elements, which is called a node.

Single linked list: A linked list composed of n nodes. Each node in this linked list contains only one pointer field.

Code implementation and analysis of singly linked list 

Structural code of singly linked list

A node in a singly linked list is composed of a data field that stores data elements and a pointer field that stores the address of the subsequent node. Therefore, assuming that this data is val, the pointer storing the address of the subsequent node is next.

typedef int SLNDataType;
typedef struct SListNode
{
	struct SListNode* next;
	SLNDataType val;
}SLNode;

Each node in a singly linked list is a structure member, that is, multiple structures form a linked list. This is different from the sequential table. Since the sequential table is stored in an array, multiple nodes are stored in an array of a structure.

Traversal printing of singly linked list

void SLTPrint(SLNode* phead)
{
	assert(phead);
	SLNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL\n");
}

Create a new head node in a singly linked list 

When creating a new head node, you need to use the malloc function. Regarding the use of malloc, I will not elaborate too much here. If you don’t understand anything, you can click on the link (click to view) to learn the use of malloc in detail. Method.

void *malloc(size_t size)  in the C library function  allocates the required memory space and returns a pointer to it.

malloc is a function that allocates memory space .

 

SLNode* SLTCreateNode(SLNDataType x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	if (newnode == NULL)
	{
		perror("malloc fail\n");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->val = x;
	return newnode;
}

End insertion of singly linked list

If this is an empty list, then directly use this singly linked list as a pointer to point to the newly created node.

 

void SLTPushBack(SLNode** pphead, SLNDataType x)
{
	assert(pphead);
	SLNode* Newnode = SLTCreateNode(x);
	if (*pphead == NULL)
	{
		*pphead = Newnode;
	}
	else
	{
		SLNode* tail = pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = Newnode;
	}
}

Header of singly linked list

 

void SLTPushFront(SLNode** pphead, SLNDataType x)
{
	assert(pphead);
	SLNode* Newnode = SLTCreateNode(x);
	Newnode->next = *pphead;
	*pphead = Newnode;
}

Tail deletion of singly linked list

 

void SLTPopBack(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}
		free(tail->next);
		tail->next = NULL;
	}
}

Header deletion of singly linked list

 

 

void SLTPopFront(SLNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	SLNode* cur = (*pphead)->next;
	//注意在单链表头删的时候,如果只有一个节点,那也是可以的,就让那个临时的为空
	free(*pphead);
	*pphead = cur;
}

Find x data in singly linked list

 

SLNode* SLTFind(SLNode* phead, SLNDataType x)
{
	SLNode* cur = phead;
	while (cur)
	{
		if (cur->val == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;
}

Insert the number x at position pos in a singly linked list

 

SLNode* SLTInsert(SLNode** pphead, SLNode* pos, SLNDataType x)
{
	assert(*pphead);
	assert(pphead);
	assert(pos);
	
	if (*pphead==pos)
	{
		SLTPushFront(pphead,x);
	}
	else
	{
		SLNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		SLNode* Newnode = SLTCreateNode(x);
		prev->next = Newnode;
		Newnode->next = pos;
	}
}

Delete the value at pos position in a singly linked list

void SLTErase(SLNode** pphead, SLNode* pos)
{
	assert(*pphead);
	assert(pphead);
	assert(pos);

	if (pos == *pphead)
	{
		SLTPopFront(pphead);
	}
	else
	{
		SLNode* prev = *pphead;
		while (prev->next!=pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

Destruction of singly linked list

void SLTDestroy(SLNode** pphead)
{
	assert(pphead);
	SLNode* cur = *pphead;
	while (cur)
	{
		SLNode* tmp = cur->next;
		free(cur);
		cur = tmp;
	}
	*pphead = NULL;
}

Guess you like

Origin blog.csdn.net/2301_78131481/article/details/134384613