初阶数据结构(C语言实现)——3.4带头双向循环链表详解(定义、增、删、查、改)

学习带头双向循环链表之前,建议先学习下顺序表,和单向不带头不循环链表。
这是博主之前的文章,欢迎学习交流
初阶数据结构(C语言实现)——3.1顺序表详解(初始化、增、删、查、改)
初阶数据结构(C语言实现)——3.3单向非循环链表详解(定义、增、删、查、改)

1 带头双向循环链表的实现

在VS2022中新建一个工程

  • List.h(带头双向循环链表的类型定义、接口函数声明、引用的头文件)
  • List.c(带头双向循环链表接口函数的实现)
  • Test.c(主函数、测试顺序表各个接口功能)

在这里插入图片描述

3. 5 带头+双向+循环链表增删查改接口实现

图示
在这里插入图片描述

特点
在这里插入图片描述

  • 实现内容

typedef int LTDataType;
typedef struct HDLListNode
{
struct HDLListNode* next;
struct HDLListNode* prve;
LTDataType data;
}HDLListNode;

//双向链表的初始化
HDLListNode* HDLListInit();
//申请一个新结点
HDLListNode* BuyListNode(LTDataType x);
//链表销毁
void HDLLDestroy(HDLListNode* phead);
//双向链表的打印
void HDLListPrint(HDLListNode* phead);
//双向链表尾插
void HDLListPushBack(HDLListNode* phead, LTDataType x);
//双向链表尾删
void HDLListPopBack(HDLListNode* phead);
//双向链表头插
void HDLListPushFront(HDLListNode* phead, LTDataType x);
//双向链表头删
void HDLListPupFront(HDLListNode* phead);
//双向链表查找
HDLListNode* HDLListFind(HDLListNode* phead, LTDataType x);
//双向链表删除pos位置的结点
HDLListNode* HDLListErase(HDLListNode* pos);
// 双向链表在pos的前面进行插入
HDLListNode* HDLListInsert(HDLListNode* pos, LTDataType x);

3.5.0 申请新结点

  • 申请新结点图解

在这里插入图片描述

  • 申请新结点代码实现
HDLListNode* BuyListNode(LTDataType x)
{
   
	HDLListNode* newNode = (HDLListNode*)malloc(sizeof(HDLListNode)); //申请空间
	if (newNode == NULL)
	{
   
		perror("BuyListNode::malloc fail!"); //如果申请失败报错
		return NULL;//返回NULL
	}
	//对新申请的结点进行初始化
	newNode->next = NULL;
	newNode->prve = NULL;
	newNode->data = x;

	return newNode;//返回新结点
}

3.5.1双向链表的初始化

  • 双向链表初始化图解

在这里插入图片描述

  • 双向链表初始化代码实现
HDLListNode* HDLListInit()
{
   
	HDLListNode* phead = BuyListNode(-1);//申请新结点
	phead->next = phead;
	phead->prve = phead;
	
	return phead;//返回头结点
}

3.5.2双向链表销毁

  • 双向链表销毁图解

在这里插入图片描述

  • 双向链表销毁代码实现
void HDLLDestroy(HDLListNode* phead)
{
   
	assert(phead);
	HDLListNode* cur = phead->next;//让cur从带哨兵的头结点之后的第一个有效结点开始遍历
	while (cur!=phead)//遍历一遍链表,一个节点一个节点的释放
	{
   
		HDLListNode* next = cur->next;//记录cur的下一个结点
		free(cur);//释放结点
		cur = next;//cur往后走
	}
	free(phead);//最后释放哨兵头结点

}

3.5.3 双向链表打印

因为头结点不带有效数值,所以让cur指针不要指向头结点,指向头结点的下一个结点,然后遍历链表打印。下次到头的时候cur =phead。

  • 双向链表打印代码实现
//双向链表的打印
void HDLListPrint(HDLListNode* phead)
{
   
	assert(phead);//断言,确保传入参数正确
	printf("<=head=>");
	HDLListNode* cur = phead->next;
	while (cur != phead)
	{
   
		printf("%d=>", cur->data);
		cur = cur->next;//cur继续往后走
	}
	//最后全部打印完之后,换行。
	printf("\n");
}

3.5.4 双向链表尾插

  • 图解尾插

在这里插入图片描述

  • 双向链表的尾插代码实现
void HDLListPushBack(HDLListNode* phead, LTDataType x)
{
   
	assert(phead);

	HDLListNode* newnode = BuyListNode(x); //申请一个新结点
	HDLListNode* tail = phead->prve;//尾结点直接就能找到
	tail->next = newnode;//让尾结点指向要插入的结点
	newnode->next = phead;//让新插入的结点指向头结点
	phead->prve = newnode;//让头结点的prve指向新的尾结点

}
  • 代码验证

在这里插入图片描述

3.5.5 双向链表尾删

  • 尾删图解

在这里插入图片描述

  • 尾删代码实现
bool isEmpty(HDLListNode* phead)
{
   
	assert(phead);
	//if (phead == NULL)
	//{
   
	//	return true;
	//}
	//else
	//{
   
	//	return false;
	//}
	//上面几行代码可以直接写成下面这一句
	return phead->next == phead; //如果相等就是true

}

void HDLListPopBack(HDLListNode* phead)
{
   
	assert(phead);//断言
	//还需要确定该链表非空
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值