当前位置:网站首页>双向带头循环链表实现
双向带头循环链表实现
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;
}
总结
总体来讲,双向带头循环虽然结构最为复杂,但是实现较为容易,并且实现也较为清晰,其各方面的效率也相当之优秀,是一个较为出色的数据结构。
边栏推荐
猜你喜欢

Qt:小的任务管理器(task)

leetcode经典例题——56.合并区间
![[Cloud Residency Co-Creation] HCSD Celebrity Live Streaming – Employment Guide](/img/50/86f0edaab8317e22c9ffdb2a2c6e93.png)
[Cloud Residency Co-Creation] HCSD Celebrity Live Streaming – Employment Guide

cannot import name ‘import_string‘ from ‘werkzeug‘【bug解决】

云函数实现网站自动化签到配置详解【Web函数/Nodejs/cookie】

JSP基本语法

MindSpore:【mindinsight】【Profiler】用execution_time推导出来的训练耗时远小于真实的耗时

双重for循环案例以及while循环和do while循环案例

EastWave应用:自动计算光子晶体透反率

MindSpore:Batchnorm only support nchw input!
随机推荐
【正点原子STM32连载】第一章 本书学习方法 摘自【正点原子】MiniPro STM32H750 开发指南_V1.1
渗透——信息收集
MindSpore:mirrorpad算子速度过慢的问题
张朝阳对话俞敏洪:谈宇宙、谈焦虑、谈创业、谈退休、谈人生
rk3399-339 usb设备复合 总体流程
Detailed explanation of switch link aggregation [Huawei eNSP]
学习在php中分析switch与ifelse的执行效率
暴力破解ssh/rdp/mysql/smb服务
LeetCode简单题之最好的扑克手牌
sqlilabs less-40
leetcode经典例题——49.字母异位词分组
Acwing 3208. Z字形扫描 偏移量+扩展图
已解决No module named ‘flask_misaka‘【BUG解决】
Post-94 Byte P7 posted the salary slip: It's really good to make up for this...
各位大佬,请问mysql数据的cdc,能指定存量数据同步的zone为utc 吗
leetcode经典例题——56.合并区间
cannot import name 'import_string' from 'werkzeug' [bug solution]
HTB-Sense
KubeDNS 和 CoreDNS
Win11如何隐藏输入法悬浮窗?