双向带头循环链表

前言:

链表的建立

建立一个结点

链表的初始化

链表的尾插

 链表的打印

链表的头插

链表的头删

链表的尾删


前言:

双向带头循环链表应该是链表中非常方便的一种,可以很容易的在任意位置上进行插入和删除,可以很容易的对链表进行管理,如果对单链表的使用不太熟悉的话可以看看这篇文章

https://blog.csdn.net/pythoncjave/article/details/125052430?spm=1001.2014.3001.5502

链表的建立

​
typedef int LTDateType;
typedef struct ListNode
{
	struct ListNode* next;//下一个指针
	struct ListNode* prev;//上一个指针
	LTDateType data; //数据域
}LTNode;

​

我们要实现的接口有:

LTNode* BuyListNode(LTDateType x);//建立一个新的节点

LTNode* ListInit(); //链表的初始化

void ListPushBack(LTNode* phead, LTDateType x);//链表的尾插

void ListPrint(LTNode* phead);//打印链表

void ListPustFront(LTNode* phead, LTDateType x);//链表的头插

void ListPopBack(LTNode* phead);//链表的尾删

void ListPopFront(LTNode* phead);//链表的头删

建立一个结点

 LTNode* BuyListNode(LTDateType x)
{
	LTNode* node = (LTNode*)malloc(sizeof(LTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	node->data = x;
	node->next = NULL;
	node->prev = NULL;
	return node;
}

 当然这个函数也可以不写,但在链表的初始化,头插,尾插中都要建立新的节点,为了方便就建立了一个函数

链表的初始化

LTNode* ListInit()
{
	 LTNode* phead;
	 phead = BuyListNode(-1);
	 phead->next = phead;
	 phead->prev = phead;
	 return phead;
}

这里将链表的头节点的下一个结点与上一个结点都指向自己,方便后面进行循环判定

链表的尾插

void ListPushBack(LTNode* phead, LTDateType x)
 {
	 LTNode* newnode = BuyListNode(x);
	 LTNode* tail = phead->prev;
//----------------------------------------
	 tail->next = newnode;
	 newnode->next = phead;
	 newnode->prev = tail;
	 phead->prev = newnode;
 }

尾插一共需要改变四个指针的指向:

①头结点的上一个结点指向(新结点newnode)  指针tail 暂时保存的是插入前的尾结点

②新结点newnode 的 newnode->next指针 应该指向

③新节点newnode 的newnode->prev指针 应该指向插入前的尾结点

④头节点的上一个结点phead->prev指向新的节点newnode

 链表的打印

 void ListPrint(LTNode* phead)
 {
	 assert(phead);
	 LTNode* cur = phead->next;
	 while (cur != phead)
	 {
		 printf("%d ", cur->data);
		 cur = cur->next;
	 }
	 printf("\n");
 }

设置一个cur指针去向后遍历,当指向头指针的时候就结束循环 

链表的头插

void ListPustFront(LTNode* phead, LTDateType x)
 {
	 if (phead->next == phead)
	 {
		 ListPushBack(phead,x);
		 return;
	 }
	 LTNode* newnode = BuyListNode(x);
	 LTNode* next = phead->next;//第一个结点
//--------------------------------phead指向的事哨兵位
	 phead->next = newnode;
	 newnode->next = next;
	 newnode->prev = phead;
	 next->prev = newnode;
 }

 头插也需要改变四个指针的指向:

①将新头给newnode

②newnode->的下一个指向 next

③newnode->上一个指向 phead

④next->prev指向新节点newnode

链表的头删

void ListPopFront(LTNode* phead)
{
    assert(phead);
	assert(phead->next != NULL);

	LTNode* next = phead->next;
	LTNode* next2 = next->next;
	phead->next = next2;
	next2->prev = phead;
	free(next);
}

 头删需要改变两个个指针的指向:

①将phead->next指向next2 也就是phead->next->next

②将next->prev指向phead

链表的尾删

void ListPopBack(LTNode* phead)
{
	assert(phead);
	assert(phead->next != phead);
	
	LTNode* tail = phead->prev;
	phead->prev = tail->prev;
	tail->prev->next = phead;

	free(tail);
}

同上所述前面的都能理解的话这个也很容易理解 

---------------------------------------------------------------------------------------------------------------------------------

总结:双向带头循环链表的插入 需要改变四个指针的指向 删除需要改变两个指针的指向 并释放空间

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Obto-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值