[data structure] circular snake? Leading bidirectional circular linked list of linked list

Keywords: data structure linked list

catalogue

1. Summary
2. Introduction of two-way circular linked list
    2.1. Bidirectional linked list
    2.2. Circular linked list
    2.3. Two way circular linked list
3. Code implementation
    3.1. Header file
    3.2. Interface documents
    3.3. Test documents
4. References

1. Summary

This paper mainly introduces the concept of two-way circular linked list and its code implementation in C language.







2. Introduction of two-way circular linked list

2.1. Bidirectional linked list

In the previous section, we introduced the one-way headless acyclic linked list, but let's think about it carefully. Since the linked list is one-way, one of the direct consequences is that we can only find the next node through the previous node, not the previous node through the latter node.

Why? Very simple, because the node only has a pointer field that identifies the address of the successor node.

So what if we want to find the previous node of a node directly? It is also very simple. Just add a pointer field to the node and record the address of the precursor.

typedef struct DLList
{
	struct DLList* next; //Pointer to record the address of the successor node
	struct DLList* prev; //Pointer that records the address of the precursor node
	DLListDataType data; //Data domain
}DLList;

2.2. Circular linked list

In addition, in a one-way headless acyclic list, we store NULL in the pointer field of the last node, indicating that there are no nodes behind it. Therefore, the linked list is acyclic.

So what if it's a circular linked list? Smart, you must have thought that as long as the next pointer field of the tail node stores the address of the head node, the whole linked list will form a perfect closed loop!

Yes, like this, I wonder if you have seen such a picture in physics class. This is a closed loop!


2.3. Two way circular linked list

OK, OK, let's not stray from the topic. Now that we have introduced what is a two-way linked list and what is a circular linked list, let's combine these two properties and take a look at the true face of Lushan, which takes the lead in the two-way circular linked list:

The linked list contains a head node. Each node has a data field and two pointer fields next and prev. The data field of the head node does not store valid data





3. Code implementation

3.1. Header file

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int DLListDataType;

typedef struct DLList
{
	struct DLList* next;
	struct DLList* prev;
	DLListDataType data;
}DLList;

DLList* DLListInit();
void DLListDestroy(DLList* phead);
void DLListPrint(const DLList* phead);
void DLListPushBack(DLList* pphead, DLListDataType x);
void DLListPushFront(DLList* pphead,DLListDataType x);
void DLListPopBack(DLList* pphead);
void DLListPopFront(DLList* pphead);
DLList* DLListFind(const DLList* phead,DLListDataType x);
void DLListInsert(DLList* pos, DLListDataType x);
void DLListErase(DLList* pos);
size_t DLListSize(DLList* phead);
bool DLListEmpty(DLList* phead);

3.2. Interface documents

Here, we need to realize the functions of initialization, addition, deletion, query and modification, printing, calculating the number of nodes and empty judgment of the linked list.

It is worth noting that the operations of header insertion, tail insertion, header deletion and tail deletion can reuse the interfaces inserted and deleted at any position.

#define _CRT_SECURE_NO_WARNINGS 1
#include "DLList.h"
DLList* DLListBuyNode(DLListDataType x)
{
	DLList* ret = (DLList*)malloc(sizeof(DLList));
	if (ret == NULL)
	{
		return NULL;
	}
	ret->data = x;
	ret->next = NULL;
	ret->prev = NULL;
	 
	return ret;
}
DLList* DLListInit()
{
	DLList* phead = DLListBuyNode(0);
	if (phead == NULL)
	{
		printf("Init Fail!\n");
		return NULL;
	}
	phead->data = 0;
	phead->next = phead;
	phead->prev = phead;
	return phead;
}
void DLListDestroy(DLList* phead)
{
	assert(phead);
	DLList* cur = phead->next;
	while (cur != phead)
	{
		DLList* tmp = cur;
		cur = cur->next;
		free(tmp);
		tmp = NULL;
	}
}
void DLListPrint(const DLList* phead)
{
	assert(phead);
	DLList* cur = phead->next;
	while (cur != phead)
	{
		printf("%d ", cur->data);
		cur = cur->next;
	}
	printf("\n");
	cur = NULL;
}
void DLListPushBack(DLList* phead, DLListDataType x)
{
	/*assert(phead);
	DLList* newnode= DLListBuyNode(x);
	if (newnode == NULL)
	{
		printf("pushback fail\n");
		exit(-1);
	}
	newnode->prev = phead->prev;
	newnode->next = phead;
	phead->prev->next = newnode;
	phead->prev = newnode;*/
	DLListInsert(phead, x);
}
void DLListPushFront(DLList* phead, DLListDataType x)
{
	/*assert(phead);
	DLList* newnode = DLListBuyNode(x);
	if (newnode == NULL)
	{
		printf("push front fai\n");
		exit(-1);
	}
	newnode->next = phead->next;
	newnode->prev = phead;
	phead->next->prev = newnode;
	phead->next = newnode;*/
	DLListInsert(phead->next, x);
}
void DLListPopBack(DLList* phead)
{

	//assert(phead);
	//if (phead == phead->prev)
	//{
	//	return;
	//}
	//DLList* tail = phead->prev->prev;
	//free(phead->prev);
	//phead->prev = NULL;
	//tail->next = phead;
	//phead->prev = tail;
	if (phead == phead->next)
		return;
	DLListErase(phead->prev);

}
void DLListPopFront(DLList* phead)
{

	/*assert(phead);
	if (phead == phead->prev)
	{
		return;
	}
	DLList* next = phead->next->next;
	free(phead->next);
	phead->next = NULL;
	phead->next = next;
	next->prev = phead;*/

	if (phead == phead->next)
		return;
	DLListErase(phead->next);

}
DLList* DLListFind(const DLList* phead, DLListDataType x)
{
	assert(phead);
	DLList* cur = phead->next;
	while (cur!=phead)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
void DLListInsert(DLList* pos , DLListDataType x) // insert before
{
	assert(pos);
	DLList* newnode = DLListBuyNode(x);
	if (newnode == NULL)
	{
		printf("newnode create failded\n");
		exit(-1);
	}
	newnode->next = pos;
	newnode->prev = pos->prev;
	pos->prev->next = newnode;
	pos->prev = newnode;
}
void DLListErase(DLList* pos)
{
	assert(pos);
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;
	free(pos);
	pos = NULL;
}

size_t DLListSize(DLList* phead)
{
	assert(phead);
	DLList* cur = phead->prev;
	size_t count = 0;
	while (cur != phead)
	{
		++count;
		cur = cur->prev;
	}
	return count;
}

bool DLListEmpty(DLList* phead)
{
	assert(phead);
	return phead == phead->prev;
}

3.3. Test documents

#include "DLList.h"

void Test1()
{
	DLList* plist = DLListInit();

	printf("empty = %d\n", DLListEmpty(plist));

	DLListPushBack(plist, 1);
	DLListPrint(plist);
	printf("empty = %d\n", DLListEmpty(plist));

	DLListPushBack(plist, 2);
	DLListPrint(plist);

	DLListPushFront(plist, 3);
	DLListPrint(plist);

	DLListPushFront(plist, 4);
	DLListPrint(plist);

	DLListPopFront(plist);
	DLListPrint(plist);

	printf("count = %d\n", DLListSize(plist));

	if (DLListFind(plist, 3))
	{
		DLListInsert(DLListFind(plist, 3), 9);
	}
	if (DLListFind(plist, 2))
	{

		DLListInsert(DLListFind(plist, 2), 9);
	}
	DLListPrint(plist);
	DLListPopBack(plist);
	DLListPopBack(plist);

	DLListPopBack(plist);

	DLListPopBack(plist);
	DLListPrint(plist);

	DLListPopBack(plist);
	DLListPrint(plist);

	DLListPrint(plist);
	DLListPopBack(plist);

	DLListPopBack(plist);
	DLListPopBack(plist);

	DLListPopBack(plist);
	DLListPrint(plist);

	DLListPrint(plist);
	DLListDestroy(plist);
	return 0;
}
int main()
{
	Test1();
	
}




4. References

1. Dahua data structure p81

Posted by Svoboda on Sat, 20 Nov 2021 19:58:03 -0800