当前位置:网站首页>双向带头循环链表实现
双向带头循环链表实现
2022-08-04 09:47:00 【kocc】
带头双向循环链表的实现
定义
typedef int LTDataType;
typedef struct ListNode
{
LTDataType data;
struct ListNode* next;//指针指向后一个结点
struct ListNode* prev;//指向前一个结点
}LTNode;
就像这样: (图拙)—_—!
实现
初始化
创建一个新结点当头结点,返回这个头结点,就当作初始化了
LTNode* ListCreate()
{
LTNode* phead = (LTNode*)malloc(sizeof(LTNode));
assert(phead);
phead->prev = phead;
phead->next = phead;//头指针指向自己,尾指针也指向自己
return phead;//返回头
}
打印
没什么好说的 遍历即可
void ListPrint(LTNode* phead)
{
assert(phead);
LTNode* cur = phead->next;//从头结点的next开始遍历
while (cur != phead)
{
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
创建一个新结点
所有插入的前提,要创建出来一个新结点,我们把它封装成一个函数
LTNode* BuyLTNode(LTDataType x)
{
LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
assert(newnode);
newnode->data = x;
newnode->next = newnode->prev = NULL;
return newnode;
}
尾插
void ListPushBack(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* newnode = BuyLTNode(x);//创建新结点
LTNode* tail = phead->prev;先把尾存起来
tail->next = newnode;把尾的next指向新结点
newnode->prev = tail;新结点的prev指向尾
newnode->next = phead;新结点的next指向头
phead->prev = newnode;头的prev指向新结点
}
尾删
void ListPopBack(LTNode* phead)
{
assert(phead);
LTNode* tail = phead->prev;//被删的尾
LTNode* newtail = tail->prev;//新的尾
free(phead->prev);//把尾删了
phead->prev = NULL;//安全
phead->prev = newtail;//把头的prev指向新的尾
newtail->next = phead;//新的尾的next指向头
}
头插
void ListPushFront(LTNode* phead, LTDataType x)
{
LTNode* newnode = BuyLTNode(x);
LTNode* prev= phead->prev;//先把尾存起来
newnode->next = phead;//新头的next指向头
phead->prev = newnode;//头的prev指向新头
prev->next = newnode;//尾的next指向新头
newnode->prev = prev;//新头的prev指向尾
}
头删
删除的是头结点的下一个结点
void ListPopFront(LTNode* phead)//删除头结点的下一个结点
{
assert(phead);
assert(phead->next != phead);
LTNode* newhead = phead->next;
LTNode* next = newhead->next;
phead->next = next;
next->prev = phead;
free(newhead);
newhead = NULL;
}
查找一个数
没啥好说,遍历,跟打印一样
LTNode* ListFind(LTNode* phead, LTDataType x)
{
assert(phead);
LTNode* cur = phead->next;
while (cur != phead)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}
在某个数字前插入
这个函数往往和find函数配合起来一起用,find找到那个数字返回该结点地址
void ListInsert(LTNode* pos, LTDataType x)
{
assert(pos);
LTNode* newnode = BuyLTNode(x);
LTNode* posPrev = pos->prev;
//跟头插非常相似
newnode->next = pos;
pos->prev = newnode;
posPrev->next = newnode;
newnode->prev = posPrev;
}
删除某个数字
void ListErase(LTNode* pos)
{
assert(pos);
LTNode* posPrev = pos->prev;
LTNode* posNext = pos->next;
posPrev->next = posNext;
posNext->prev = posPrev;
pos = NULL;
}
总结
总体来讲,双向带头循环虽然结构最为复杂,但是实现较为容易,并且实现也较为清晰,其各方面的效率也相当之优秀,是一个较为出色的数据结构。
边栏推荐
猜你喜欢
LeetCode中等题之旋转图像
张朝阳对话俞敏洪:谈宇宙、谈焦虑、谈创业、谈退休、谈人生
IDEA启动热部署
Cloud function to achieve automatic website check-in configuration details [Web function/Nodejs/cookie]
sqlilabs less-38~39
LeetCode简单题之最好的扑克手牌
2022-08-03 第六小组 瞒春 学习笔记
加降息与BTC流动性事件策略研究
数据使用要谨慎——不良数据带来严重后果
No module named 'flask_misaka' has been resolved [BUG solution]
随机推荐
浅聊偏函数
加降息与BTC流动性事件策略研究
matlab练习程序(多线段交点)
leetcode二叉树系列(二叉搜索树篇)
三层交换机配置MSTP协议详解【华为eNSP实验】
TiCDC同步延迟问题处理
IDEA 自动导入的配置(Auto import)
EastWave应用:自动计算光子晶体透反率
TiFlash 源码阅读(五) DeltaTree 存储引擎设计及实现分析 - Part 2
关于ARM2440中断源个数的一点想法[通俗易懂]
请你谈谈网站是如何进行访问的?【web领域面试题】
被Win11安全中心误删除的文件怎么恢复?
【正点原子STM32连载】第一章 本书学习方法 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
什么是元宇宙?
MindSpore:图算融合报错
LeetCode581+621+207
数据万象内容审核 — 共建安全互联网,专项开展“清朗”直播整治行动
双指针方法
No module named 'flask_misaka' has been resolved [BUG solution]
LVS负载均衡群集