Data structure-the structure and realization of two-way circular linked list (C language)

1. The structure and realization of doubly linked list

1.1 Leading two-way circular linked list

The structure is the most complex , and is generally used to store data separately. The linked list data structure used in practice is a two-way circular linked list that takes the lead. In addition, although the structure of this structure is complex, you will find that the structure will bring a lot of advantages after using the code to achieve it, but the implementation is simple, and we will know when the code is implemented later.

Insert picture description here

1.2 The realization of the lead two-way circular linked list

// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
    
    
	LTDataType _data;			
	struct ListNode* _next;	
	struct ListNode* _prev;
}ListNode;

Second, the realization of the interface of the doubly linked list

2.1 Create a doubly linked list

Create a head node, apply for space, newNode->_next = newNode->_prev = newNode;
Insert picture description here

ListNode* BuyNode(LTDataType x)
{
    
    
	ListNode* newNode = (ListNode *)malloc(sizeof(ListNode));
	newNode->_data = x;
	newNode->_next = newNode->_prev = NULL;
	return newNode;

}

// 创建返回链表的头结点.
ListNode* ListCreate()
{
    
    
	ListNode* Head = BuyNode(0);
	Head->_next = Head->_prev = Head;
	return Head;
}

2.2 Destruction of doubly linked list

//双向链表的清除,保留头节点
void ListClear(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	//遍历每个节点并释放
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	pHead->_next = pHead->_prev = pHead;
}

// 双向链表销毁
void ListDestory(ListNode** ppHead)
{
    
    
	assert(*ppHead);
	ListClear(*ppHead);
	free(*ppHead);
	*ppHead = NULL;
}

2.3 Doubly linked list is inserted in front of pos

Insert picture description here

// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* newNode = BuyNode(x);
	newNode->_prev = prev;	//1.
	prev->_next = newNode;	//2.
	pos->_prev = newNode;	//3.
	newNode->_next = pos;	//4.


}

2.4 Doubly linked list deletes the node at position pos

Insert picture description here

// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* next = pos->_next;	//pos的后一个节点
	
	free(pos);
	prev->_next = next;	//1.
	next->_prev = prev;	//2.

}

2.5 Doubly linked list printing

// 双向链表打印
void ListPrint(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	
	遍历每个节点并打印
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;	//next指向下一个节点
		printf("%d ", cur->_data);	//打印当前节点
		cur = next;		//cur指向下一个节点
	}
	printf("\n");

}

2.5 End Insertion of Double Linked List

Insert picture description here
The tail insertion is actually to insert the node in front of the head node , so you can directly call the interface written before, or you can gradually implement it yourself

// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead, x);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//ListNode* newNode = BuyNode(x);	//创建一个新节点
	//tail->_next = newNode;	//1.
	//newNode->_prev = tail;	//2.
	//newNode->_next = pHead;	//3.
	//pHead->_prev = newNode;	//4.
}

2.6 End deletion of doubly linked list

Tail deletion is to delete the last node of the doubly linked list, and the position of deletion is the previous node of the head node

// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
    
    
	assert(pHead);

	ListErase(pHead->_prev);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//if (tail == pHead)	//只有头节点说明双向链表为空,直接返回
	//{
    
    
	//	return;
	//}
	//ListNode* prev = tail->_prev;	//尾节点的前一个节点,即新的尾节点
	//free(tail);		//释放尾节点
	//prev->_next = pHead;	//1.新的尾节点next指向head
	//pHead->_prev = prev;	//2.head的prev指向新的尾节点
}

2.7 Double-linked meter header insertion

Head insert is inserted behind the head node

// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead->_next, x);


}

2.8 Deletion of Doubly Linked List Header

Header delete is to delete the element after the head node

// 双向链表头删
void ListPopFront(ListNode* pHead)
{
    
    
	assert(pHead);
	
	ListErase(pHead->_next);


}

2.9 Doubly Linked List Lookup

// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		if (cur->_data == x)
		{
    
    
			return cur;
		}
		cur = next;
	}
	return NULL;
}

Three, the code list

3.1 List.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<windows.h>

// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{
    
    
	LTDataType _data;			
	struct ListNode* _next;	
	struct ListNode* _prev;
}ListNode;

// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListClear(ListNode* pHead);
void ListDestory(ListNode** ppHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);

3.2 List.c

#include "List.h"


ListNode* BuyNode(LTDataType x)
{
    
    
	ListNode* newNode = (ListNode *)malloc(sizeof(ListNode));
	newNode->_data = x;
	newNode->_next = newNode->_prev = NULL;
	return newNode;

}

// 创建返回链表的头结点.
ListNode* ListCreate()
{
    
    
	ListNode* Head = BuyNode(0);
	Head->_next = Head->_prev = Head;
	return Head;
}


//双向链表的清除,保留头节点
void ListClear(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	//遍历每个节点并释放
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		free(cur);
		cur = next;
	}
	pHead->_next = pHead->_prev = pHead;
}

// 双向链表销毁
void ListDestory(ListNode** ppHead)
{
    
    
	assert(*ppHead);
	ListClear(*ppHead);
	free(*ppHead);
	*ppHead = NULL;
}

// 双向链表打印
void ListPrint(ListNode* pHead)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	
	遍历每个节点并打印
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;	//next指向下一个节点
		printf("%d ", cur->_data);	//打印当前节点
		cur = next;		//cur指向下一个节点
	}
	printf("\n");

}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead, x);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//ListNode* newNode = BuyNode(x);	//创建一个新节点
	//tail->_next = newNode;	//1.
	//newNode->_prev = tail;	//2.
	//newNode->_next = pHead;	//3.
	//pHead->_prev = newNode;	//4.
}
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{
    
    
	assert(pHead);

	ListErase(pHead->_prev);

	//ListNode* tail = pHead->_prev;	//找到尾节点
	//if (tail == pHead)	//只有头节点说明双向链表为空,直接返回
	//{
    
    
	//	return;
	//}
	//ListNode* prev = tail->_prev;	//尾节点的前一个节点,即新的尾节点
	//free(tail);		//释放尾节点
	//prev->_next = pHead;	//1.新的尾节点next指向head
	//pHead->_prev = prev;	//2.head的prev指向新的尾节点
}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListInsert(pHead->_next, x);


}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{
    
    
	assert(pHead);
	
	ListErase(pHead->_next);


}

// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{
    
    
	assert(pHead);

	ListNode* cur = pHead->_next;
	while (cur != pHead)
	{
    
    
		ListNode* next = cur->_next;
		if (cur->_data == x)
		{
    
    
			return cur;
		}
		cur = next;
	}
	return NULL;
}
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* newNode = BuyNode(x);
	newNode->_prev = prev;	//1.
	prev->_next = newNode;	//2.
	pos->_prev = newNode;	//3.
	newNode->_next = pos;	//4.


}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{
    
    
	assert(pos);

	ListNode* prev = pos->_prev;	//pos的前一个结点
	ListNode* next = pos->_next;	//pos的后一个节点
	
	free(pos);
	prev->_next = next;	//1.
	next->_prev = prev;	//2.

}

3.3 test.c

#include"List.h"

void TestList()
{
    
    
	ListNode *p;
	p = ListCreate();
	ListPushFront(p, 5);
	ListPushFront(p, 4);
	ListPushFront(p, 3);
	ListPushFront(p, 2);
	ListPushFront(p, 1);
	ListPrint(p);

	ListPopFront(p);
	ListPopFront(p);
	ListPopFront(p);
	ListPopFront(p);
	ListPopFront(p);
	ListPrint(p);

	ListPushBack(p, 1);
	ListPushBack(p, 2);
	ListPushBack(p, 3);
	ListPushBack(p, 4);
	ListPushBack(p, 5);
	ListPrint(p);

	ListPopBack(p);
	ListPopBack(p);
	ListPopBack(p);
	ListPopBack(p);
	ListPopBack(p);
	ListPrint(p);


	//ListDestory(&p);

	ListPushFront(p, 5);
	ListPushFront(p, 4);
	ListPushFront(p, 3);
	ListPushFront(p, 2);
	ListPushFront(p, 1);
	ListPrint(p);

	ListNode* pos = ListFind(p, 3);
	pos->_data = 30;
	ListPrint(p);

	ListInsert(pos, 33);
	ListPrint(p);
	ListErase(pos);
	ListPrint(p);

	ListDestory(&p);
}

int main()
{
    
    
	TestList();
	system("pause");
	return 0;
}

Four, test results

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_40076022/article/details/112526801