超实用链表(带头节点双向循环链表)

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了超实用链表(带头节点双向循环链表)相关的知识,希望对你有一定的参考价值。

逻辑结构

在这里插入图片描述

物理结构

带头节点双向循环链表,有两个指针域,一个数据域。一个指针存前面一个结点的地址,一个指针存下一个结点的地址。

typedef int Datatype;

typedef struct Dlist{
	Datatype data;
	struct Dlist *next;
	struct Dlist *pre;
}Dlist;

实现功能

Dlist *DlistCreate(Datatype x);//创建结点
Dlist *DlistInit(Datatype x);//初始化头节点
void DlistPushFront(Dlist *list, Datatype x);//头插
void DlistPopFront(Dlist *list);//头删
void DlistPushAfter(Dlist *list, Datatype x);//尾插
void DlistPopAfter(Dlist *list);//尾删
Dlist *DlistFind(Dlist *list, Datatype x);//找某一结点
void DlistInsert(Dlist *pos, Datatype x);//在pos前插
void DlistErease(Dlist *pos);//将pos删除
void DlistPrint(Dlist *list);//打印
int DlistIsEmpty(Dlist *list);//判定空
void DlistDestory(Dlist *list);//释放结点,除头节点

代码

1.创建链表头节点

Dlist *DlistCreate(Datatype x){//创建结点
	Dlist *newnode = (Dlist *)malloc(sizeof(Dlist));
	newnode->data = x;
	newnode->next = NULL;
	newnode->pre = NULL;
	return newnode;
}

Dlist *DlistInit(Datatype x){//将头节点初始化,循环自己指向自己
	Dlist *head = DlistCreate(x);
	head->next = head;
	head->pre = head;
	return head;
}

2.头/尾插,在pos前插入
在这里插入图片描述
只有一个头节点的情况该代码也适用。

void DlistPushFront(Dlist *list, Datatype x){//头插
	assert(list);
	Dlist *newnode = DlistCreate(x);

	Dlist *tail = list->next;
	list->next = newnode;
	newnode->pre = list;
	newnode->next = tail;
	tail->pre = newnode;
}
void DlistPushAfter(Dlist *list, Datatype x){//尾插
	assert(list);
	Dlist *newnode = DlistCreate(x);
	Dlist *tail = list->pre;

	tail->next = newnode;
	newnode->next = list;
	newnode->pre = tail;
	list->pre = newnode;
	DlistInsert(list, x);
}

void DlistInsert(Dlist *pos, Datatype x){//pos前插入,尾插相当于在list的前面插
	assert(pos);
	Dlist *tail = pos->pre;
	Dlist *newnode = DlistCreate(x);

	tail->next = newnode;
	newnode->pre = tail;
	newnode->next = pos;
	pos->pre = newnode;

}

3.头/尾删,将pos位置删除
在这里插入图片描述

void DlistPopFront(Dlist *list){//头删
	assert(list);
	Dlist *tail = list->next;
	Dlist *next = tail->next;

	list->next = next;
	next->pre = list;
	free(tail);
}

void DlistPopAfter(Dlist *list){//尾删
	assert(list);
	assert(list->next != list);
	Dlist *tail = list->pre;
	Dlist *pre = tail->pre;

	pre->next = list;
	list->pre = pre;
	free(tail);
	DlistErease(list->pre);
}

void DlistErease(Dlist *pos){//将pos位置删除
	assert(pos);
	//assert(pos->next != list);
	Dlist *tail = pos->pre;
	Dlist *next = pos->next;

	tail->next = next;
	next->pre = tail;
	free(pos);
}

4.找到值为X的结点

Dlist *DlistFind(Dlist *list, Datatype x){
	assert(list);
	Dlist *cur = list->next;//注意从头节点下一个开始
	while (cur != list){
		if (cur->data == x){
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

5.判端链表是否为空

int DlistIsEmpty(Dlist *list){
	if (list->next == list){
		return 1;
	}
	return 0;
}

6.销毁结点

void DlistDestory(Dlist *list){
	assert(list);
	Dlist *cur = list->next;
	while (cur->next != list){
		Dlist *next = cur->next;
		free(cur);
		cur = next;
	}
}

验证代码

#include"Doublelist.h"


static void Test1(Dlist *list){
	DlistPushFront(list, 4);
	DlistPushFront(list, 3);
	DlistPushFront(list, 2);
	DlistPushFront(list, 1);
	DlistPrint(list);
	DlistPopFront(list);
	DlistPopFront(list);
	DlistPrint(list);
	DlistPushAfter(list, 5);
	DlistPushAfter(list, 6);
	DlistPrint(list);
	DlistPopAfter(list);
	DlistPopAfter(list);
	DlistPrint(list);
	Dlist *pos = DlistFind(list, 4);
	if (pos){
		DlistInsert(pos, 40);
		DlistPrint(list);
	}
	DlistPopAfter(list);
	//DlistPopAfter(list);
	//DlistPopAfter(list);
	int i = DlistIsEmpty(list);
	printf("%d\\n", i);
	DlistDestory(list);
	free(list);//释放头节点

}

int main(){
	Dlist *head = DlistInit(0);
	Test1(head);

	system("pause");
	return 0;
}

以上是关于超实用链表(带头节点双向循环链表)的主要内容,如果未能解决你的问题,请参考以下文章

带头节点的双向链表

数据结构带头双向循环链表

数据结构——带头双向循环链表

C语言实现双向非循环链表(带头结点尾结点)的节点插入

新手向超好理解的带头双向循环链表

新手向超好理解的带头双向循环链表