C language-add, delete, check and modify the two-way leading circular linked list and its advantages and disadvantages


Preface

There are many types of linked lists. Among them, one-way non-leaded non-circular linked lists and two-way led circular linked lists are used. Both types of linked lists have their own applications.
The structure of the bidirectional leading circular linked list is the most complicated, and it 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. Today, I will use the C language to realize the addition, deletion, and modification of the leading doubly linked list.


1. Two-way leading circular linked list

1. Two-way leading circular linked list structure

First of all: look at the structure of the two-way leading circular linked list

Insert picture description here
It can be seen that each node of the two-way leading circular linked list is connected to the front and back, thus forming a loop. To realize this structure, you need to create a head node. The tail pointer of the head node points to itself, and the head pointer also points to it. On this basis, it realizes the insertion and deletion of other nodes.

1. Two-way leading circular linked list implementation code

The following is the code part: the
header file
ListNode.h

#define pragama once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

//typedef方便修改结构体变量的类型
typedef int LTDataType;

//构建链表结构体,结构体变量包括头指针,尾指针及data值
typedef struct ListNode {
    
    
	
	struct ListNode* pre;
	struct ListNode* next;
	LTDataType data;

}ListNode;

//创建新节点
ListNode* BuyListNode(LTDataType x);
//链表初始化->创造头结点
ListNode* InitListNode();
//打印链表
void ListPrint(ListNode* phead);
//销毁链表
void ListDistory(ListNode* phead);

//增删查改
void ListPushBack(ListNode* phead, LTDataType x);
void ListPushFront(ListNode* phead, LTDataType x);
void ListPopBack(ListNode* phead);
void ListPopFront(ListNode* phead);
ListNode* ListFind(ListNode* phead, LTDataType x);
void ListInsert(ListNode* pos, LTDataType x);
void ListErase(ListNode* pos);
void Listchange(ListNode* pos, LTDataType x);

Body
ListNode.c

#include"ListNode.h"



ListNode* BuyListNode(LTDataType x)
{
    
    
	ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));
	newnode->data = x;
	newnode->next = NULL;
	newnode->pre = NULL;


	return newnode;
}


ListNode* InitListNode()
{
    
    
	//构造头结点
	ListNode* phead = (ListNode*)malloc(sizeof(ListNode));
	phead->next = phead;
	phead->pre = phead;

	return phead;
}

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

	//从头结点后开始,到头结点结束
	ListNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		printf("%d", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void ListDistory(ListNode* phead)
{
    
    
	ListNode* cur = phead->next;
	while (cur != phead)
	{
    
    
		ListNode* next = cur->next;
		ListErase(cur);
		cur = next;
	}
	free(phead);
	phead = NULL;
}

//以下注释掉的代码段和留下的代码功能是一样的
void ListPushBack(ListNode* phead, LTDataType x)
{
    
    
	/*assert(phead);

	ListNode* newnode = BuyListNode(x);
	ListNode* tail = phead->pre;

	tail->next = newnode;
	newnode->pre = tail;
	newnode->next = phead;
	phead->pre = newnode;*/
	ListInsert(phead, x);
}

void ListPushFront(ListNode* phead, LTDataType x)
{
    
    
	/*assert(phead);

	ListNode* next = phead->next;
	ListNode* newnode = buyListNode(x);

	newnode->next = next;
	next->pre = newnode;
	phead->next = newnode;
	newnode->pre = phead;*/
	ListInsert(phead->next, x);

}

void ListPopBack(ListNode* phead)
{
    
    
	/*assert(phead);
	assert(phead->next != phead);
	
	ListNode* tail = phead->pre;
	ListNode* tailpre = tail ->pre;
	
	tailpre->next = phead;
	phead->pre = tailpre;
	
	free(tail);*/
	ListErase(phead->pre);
}

void ListPopFront(ListNode* phead)
{
    
    
	/*assert(phead);
	assert(phead->next != phead);
	
	ListNode* next = phead->next;
	ListNode* newnext = next ->next;
	
	phead->next = newnext;
	newnext->pre = phead;

	free(next);*/
	ListErase(phead->next);
}

ListNode* ListFind(ListNode* phead, LTDataType x)
{
    
    
	assert(phead);

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

//POS之前插入
void ListInsert(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);
	ListNode* pospre = pos->pre;
	ListNode* newnode = BuyListNode(x);
	
	pospre->next = newnode;
	newnode->pre = pospre;
	newnode->next = pos;
	pos->pre = newnode;

}
//pos不能是phead! 否则会破坏双向链表的结构;
void ListErase(ListNode* pos)
{
    
    
	assert(pos);
	ListNode* pospre = pos->pre;
	ListNode* posnext = pos->next;

	pospre->next = posnext;
	posnext->pre = pospre;
	free(pos);
}
void Listchange(ListNode* pos, LTDataType x)
{
    
    
	assert(pos);
	pos->data = x;
}

Test code
test.c

#include"ListNode.h"


void test()
{
    
    
	ListNode* phead = InitListNode();
	ListPushBack(phead, 1);
	ListPushBack(phead, 2);
	ListPushBack(phead, 3);
	ListPushBack(phead, 4);
	ListPushBack(phead, 5);
	ListPushFront(phead, 6);
	ListPrint(phead);

	ListNode* pos = ListFind(phead, 2);
	ListInsert(pos, 8);
	ListErase(pos);
	ListPrint(phead);
	ListNode* pos2 = ListFind(phead, 4);
	Listchange(pos2, 9);

	//ListDistory(phead);
	ListPrint(phead);

}
int main()
{
    
    
	test();
	return 0;
}

operation result
![Insert picture description here](https://img-blog.csdnimg.cn/20210202194546953.png

Second, the advantages and disadvantages of the two-way leading circular linked list

The advantages and disadvantages of the following two-way circular list are compared with the sequential table and the one-way non-circular linked list, so the advantages and disadvantages of the following sequential table are summarized at the same time.

1. Advantages and disadvantages of two-way leading circular linked list

  • Advantages : It supports O(1) insertion and deletion at any position, no need to expand, and there is no waste of space.
  • Disadvantages : random access is not supported, and the cache hit rate is relatively low.

2. Advantages and disadvantages of sequence table

advantage:

  • Relatively speaking, the space utilization rate is higher, no additional space is needed, and the space is small (the linked list needs to store pointers).
  • The physical space is continuous. Support random access, you can use subscript access (the biggest advantage); cache hit rate is higher.

Disadvantages:

  • Inserting or deleting data in the header or in the middle requires moving the data one by one, and the time complexity is O(N).
  • When the space is insufficient, the capacity needs to be increased. Generally, the capacity is increased by multiples, so there may be a certain amount of memory waste.

Guess you like

Origin blog.csdn.net/weixin_47460769/article/details/113572440