[Data structure] Sequence list and linked list (below)

[Data structure] Sequence list and linked list (above):

https://blog.csdn.net/m0_51866180/article/details/122301767?spm=1001.2014.3001.5502icon-default.png?t=M0H8https://blog.csdn.net/m0_51866180/article/details/122301767?spm=1001.2014.3001.5502

[Objectives of this section]
 3. Linked list
 4. The difference between sequential list and linked list


3. Linked list

3.1 Concept and structure of linked list

Concept: Linked list is a non-consecutive and non-sequential storage structure in physical storage structure. The logical order of data elements is realized through the link order of pointers in the linked list.

 

real data structure 


3.2 Classification of linked lists 

In practice, the structure of linked lists is very diverse. There are 8 linked list structures in combination of the following situations:

1. One-way or two-way


2. To lead or not to lead

 3. Cyclic or acyclic

 


 

Although there are so many linked list structures, there are two structures that are most commonly used in practice:

1. Headless one-way acyclic linked list: The structure is simple, and it is generally not used to store data alone. In practice, it is more of a substructure of other data structures, such as hash buckets, graph adjacency lists, and so on. In addition, this structure appears a lot in the written test interview.


2. Leading doubly circular linked list: The structure is the most complex, and it is generally used to store data separately. The linked list data structures used in practice are all leading doubly circular linked lists. In addition, although the structure of this structure is complex, it will be found that the structure will bring many advantages after using the code to implement it, but the implementation is simple, and we will know it after the code is implemented.


 3.3 Implementation of linked list

// 1、无头+单向+非循环链表增删查改实现
typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;
}SListNode;
// 动态申请一个节点
SListNode* BuySListNode(SLTDateType x);
// 单链表打印
void SListPrint(SListNode* plist);
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x);
// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x);
// 单链表的尾删
void SListPopBack(SListNode** pplist);
// 单链表头删
void SListPopFront(SListNode** pplist);
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x);
// 单链表在pos位置之后插入x
// 分析思考为什么不在pos位置之前插入?
void SListInsertAfter(SListNode* pos, SLTDateType x);
// 单链表删除pos位置之后的值
// 分析思考为什么不删除pos位置?
void SListEraseAfter(SListNode* pos);

 

#include "SList.h"

SLTNode* BuyListNode(SLTDateType x)
{
	// 1M = 1024KB = 1024 * 1024 Byte
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

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

void SListPushBack(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);

	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		// 找到尾节点
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = newnode;
	}	
}

void SListPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);

	newnode->next = *pphead;
	*pphead = newnode;
}

void SListPopBack(SLTNode** pphead)
{
	// 温柔的一点
	/*if (*pphead == NULL)
	{
	return;
	}*/

	// 粗暴一点
	assert(*pphead != NULL);
	
	// 1、一个节点
	// 2、两个及以上节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		//SLTNode* prev = NULL;
		//SLTNode* tail = *pphead;
		while (tail->next != NULL)
		//while (tail->next)
		//{
		//	prev = tail;
		//	tail = tail->next;
		//}

		//free(tail);
		//tail = NULL;
		//prev->next = NULL;

		SLTNode* tail = *pphead;
		while (tail->next->next)
		{
			tail = tail->next;
		}

		free(tail->next);
		tail->next = NULL;
	}
}

void SListPopFront(SLTNode** pphead)
{
	//if (*pphead == NULL)
	//	return;
	assert(*pphead != NULL);

	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

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

	return NULL;
}

// 在pos的后面插入,这个更适合,也更简单
void SListInsertAfter(SLTNode* pos, SLTDateType x);

// 在pos位置之前去插入一个节点
void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else
	{
		// 找到pos的前一个位置
		SLTNode* posPrev = *pphead;
		while (posPrev->next != pos)
		{
			posPrev = posPrev->next;
		}

		posPrev->next = newnode;
		newnode->next = pos;
	}
}

void SListErase(SLTNode** pphead, SLTNode* pos);
void SListDestroy(SLTNode** pphead);

 3.4 Implementation of Doubly Linked List

// 2、带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
	LTDataType _data;
	struct ListNode* next;
	struct ListNode* prev;
}ListNode;
// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* plist);
// 双向链表打印
void ListPrint(ListNode* plist);
// 双向链表尾插
void ListPushBack(ListNode* plist, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* plist);
// 双向链表头插
void ListPushFront(ListNode* plist, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* plist);
// 双向链表查找
ListNode* ListFind(ListNode* plist, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

 

#include "List.h"

LTNode* ListInit()
{
	// ڱλͷ
	LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
	phead->next = phead;
	phead->prev = phead;

	return phead;
}

LTNode* BuyListNode(LTDateType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}

void ListPrint(LTNode* phead)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void ListPushBack(LTNode* phead, LTDateType x)
{
	assert(phead);

	//LTNode* tail = phead->prev;
	//LTNode* newnode = BuyListNode(x);

	 phead                   tail  newnode
	//tail->next = newnode;
	//newnode->prev = tail;
	//newnode->next = phead;
	//phead->prev = newnode;

	ListInsert(phead, x);
}

//void ListPopBack(LTNode* phead)
//{
//	assert(phead);
//	assert(phead->next != phead);
//
//	LTNode* tail = phead->prev;
//	LTNode* tailPrev = tail->prev;
//	free(tail);
//
//	tailPrev->next = phead;
//	phead->prev = tailPrev;
//}

void ListPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);

	/*LTNode* tail = phead->prev;

	phead->prev = tail->prev;
	tail->prev->next = phead;

	free(tail);*/
	ListErase(phead->prev);
}

void ListPushFront(LTNode* phead, LTDateType x)
{
	assert(phead);
	/*LTNode* newnode = BuyListNode(x);
	LTNode* next = phead->next;

	phead->next = newnode;
	newnode->prev = phead;

	newnode->next = next;
	next->prev = newnode;*/

	ListInsert(phead->next, x);
}

void ListPopFront(LTNode* phead)
{
	assert(phead);
	// 
	assert(phead->next != phead);

	//LTNode* next = phead->next;
	//LTNode* nextNext = next->next;

	//phead->next = nextNext;
	//nextNext->prev = phead;
	//free(next);

	ListErase(phead->next);
}

LTNode* ListFind(LTNode* phead, LTDateType x)
{
	assert(phead);

	LTNode* cur = phead->next;
	while (cur != phead)
	{
		if (cur->data == x)
		{
			return cur;
		}

		cur = cur->next;
	}

	return NULL;
}

// posλ֮ǰ
void ListInsert(LTNode* pos, LTDateType x)
{
	assert(pos);
	LTNode* posPrev = pos->prev;
	LTNode* newnode = BuyListNode(x);

	// posPrev newnode pos
	posPrev->next = newnode;
	newnode->prev = posPrev;
	newnode->next = pos;
	pos->prev = newnode;
}

// ɾposλ
void ListErase(LTNode* pos)
{
	assert(pos);

	LTNode* posPrev = pos->prev;
	LTNode* posNext = pos->next;

	posPrev->next = posNext;
	posNext->prev = posPrev;
	free(pos);
	pos = NULL;
}

void ListDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}

	free(phead);
	phead = NULL;
}

 


4. The difference between sequential list and linked list

 Note: Cache utilization refers to storage architecture and local principles.

Guess you like

Origin blog.csdn.net/m0_51866180/article/details/122585024