0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

双向循环链表的创建

C语言编程学习基地 来源:C语言编程学习基地 作者:C语言编程学习基地 2022-05-24 16:27 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

双向循环链表和它名字的表意一样,就是把双向链表的两头连接,使其成为了一个环状链表。只需要将表中最后一个节点的next指针指向头节点,头节点的prior指针指向尾节点,链表就能成环儿,如图所示:

c0a72b46-db39-11ec-ba43-dac502259ad0.jpg

需要注意的是,虽然双向循环链表成环状,但本质上还是双向链表,因此在双向循环链表中,依然能够找到头指针和头节点等。双向循环链表和双向链表相比,唯一的不同就是双向循环链表首尾相连,其他都完全一样。

注意:因为我上面已经讲了双向链表,所以这里只注重讲他们的实现差异。另因为带头节点会更好操作,所以我的代码都有头节点。

1、双向循环链表的创建

初始化时需要将头节点的next和prior都指向自己。

c0be579e-db39-11ec-ba43-dac502259ad0.jpg

//1、初始化双向循环链表(带头节点)

Status initLinkList(LinkList *list){

//创建头节点

*list = malloc(sizeof(Node));

if (*list == NULL) {

return ERROR;

}

//前驱和后继都指向自己

(*list)->prior = *list;

(*list)->data = -1;

(*list)->next = *list;

printf("已初始化链表~ ");

return OK;

}

2、遍历双向循环链表

注意它的尾节点的next不再是Null,而是头节点

//2、遍历双向循环链表

void printfLinkLisk(LinkList list){

printf("遍历链表: ");

if (list == NULL || list->next == list) {

printf("这是一个空链表 ");

return;

}

LinkList p = list;

//判断next是否全部正确

printf("根据next从前往后遍历:");

while (p->next != list) {

printf("%d ",p->next->data);

p = p->next;

}

printf(" ");

//判断prior是否全部正确

printf("根据prior从后往前遍历:");

while (p != list) {

printf("%d ",p->data);

p = p->prior;

}

printf(" ");

}

3、根据索引位置添加节点

这里不需要判断尾节点的next是否为Null,因为它会指向头节点。

//3、根据索引位置插入数据至链表中

Status insertLinkList(LinkList *list, int index, ElemType data){

if (list == NULL || index < 0) {

return ERROR;

}

int i = 0;

LinkList priorNode = *list;

//判断插入的位置,这里开始位置是0,index超过链表长度则插入末尾

while (i < index && priorNode->next != *list) {

priorNode = priorNode->next;

i++;

}

LinkList newNode = malloc(sizeof(Node));

if (newNode == NULL) {

return ERROR;

}

newNode->data = data;

//插入操作共四步,看好了,别眨眼

//1.将priorNode->next节点的前驱指向新节点

priorNode->next->prior = newNode;

//2.将新节点->next指向原来的priorNode->next

newNode->next = priorNode->next;

//3.将priorNode->next指向新节点

priorNode->next = newNode;

//4.新节点的前驱指向priorNode

newNode->prior = priorNode;

return OK;

}

4、根据索引位置删除节点

这里不需要判断尾节点的next是否为Null,因为它会指向头节点。

//4、根据索引位置删除节点

Status deleteLinkListByIndex(LinkList *list, int index, ElemType *data){

if (*list == NULL || index < 0) {

return ERROR;

}

LinkList locaNode = *list;

int i = 0;

//注意别删了头节点

while (i <= index) {

locaNode = locaNode->next;

if (locaNode == *list) {

printf("没有这个你想要删除的节点 ");

return ERROR;

}

i++;

}

//开始删除,只需要做两步

locaNode->prior->next = locaNode->next;

locaNode->next->prior = locaNode->prior;

*data = locaNode->data;

free(locaNode);

return OK;

}

5、根据存储的值删除节点

这里不需要判断尾节点的next是否为Null,因为它会指向头节点。

//5、根据存储的值删除节点

Status deleteLinkListByData(LinkList *list, ElemType data){

if (*list == NULL) {

return ERROR;

}

LinkList locaNode = (*list)->next;

while (locaNode != *list) {

if (locaNode->data == data) {

break;

}

locaNode = locaNode->next;

}

if (locaNode == *list) {

printf("没有这个你想要删除的节点 ");

return ERROR;

}

//开始删除,只需要做两步

locaNode->prior->next = locaNode->next;

locaNode->next->prior = locaNode->prior;

free(locaNode);

return OK;

}

6、根据值查找节点

尾节点的next可是头节点哦,找到它就是最后一个了。

//6、查找元素

Status selectNode(LinkList list, ElemType data, LinkList *locaNode){

if (list == NULL) {

return ERROR;

}

LinkList p = list->next;

while (p != list) {

if (p->data == data) {

*locaNode = p;

break;

}

p = p->next;

}

if (*locaNode == NULL) {

printf("没有这个你想要的节点 ");

return ERROR;

}

else {

return OK;

}

}

其它代码

#include "stdlib.h"

#define OK 1

#define ERROR 0

//元素类型

typedef int ElemType;

//状态类型

typedef int Status;

//定义节点结构体

typedef struct Node {

struct Node *prior;

ElemType data;

struct Node *next;

} Node;

typedef Node *LinkList;

int main(int argc, const char * argv[]) {

LinkList list;

initLinkList(&list);

for (int i = 0; i < 10; i ++) {

insertLinkList(&list, i, i);

}

printfLinkLisk(list);

int index, data;

printf("输入你想插入的位置(从0开始)和存储的值:");

scanf("%d %d",&index,&data);

insertLinkList(&list, index, data);

printfLinkLisk(list);

printf("输入你想删除的位置(从0开始):");

scanf("%d",&index);

deleteLinkListByIndex(&list, index, &data);

printfLinkLisk(list);

printf("输入你想删除的节点的值(只删最前的那个):");

scanf("%d",&data);

deleteLinkListByData(&list, data);

printfLinkLisk(list);

printf(" ");

return 0;

}

输出结果:

c0cf2b46-db39-11ec-ba43-dac502259ad0.jpg

—END—

审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 节点
    +关注

    关注

    0

    文章

    230

    浏览量

    25671
  • 链表
    +关注

    关注

    0

    文章

    80

    浏览量

    11086

原文标题:【C语言教程】“双向循环链表”学习总结及其代码实现!

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    什么是热循环试验?有哪些设备?怎么做热循环试验?

    循环试验,也称为温度循环试验、高低温循环试验,是一种在常压下进行试件温度循环的可靠性试验,用于评估材料、组件或产品在温度变化条件下的耐久性和可靠性。通过模拟实际使用过程中可能遇到的温
    的头像 发表于 04-22 15:20 75次阅读
    什么是热<b class='flag-5'>循环</b>试验?有哪些设备?怎么做热<b class='flag-5'>循环</b>试验?

    【快速温变循环】快速温变循环试验箱的“循环”之道:宏展科技如何定义“一个循环

    在军工、航天、汽车电子等高端制造领域,快速温变循环试验是验证产品可靠性的核心手段。然而,“一个循环”到底如何定义?是简单的升降温,还是对速率、驻留时间、温变曲线精度、循环重复性的严苛约束?广东宏展
    的头像 发表于 04-16 09:38 288次阅读
    【快速温变<b class='flag-5'>循环</b>】快速温变<b class='flag-5'>循环</b>试验箱的“<b class='flag-5'>循环</b>”之道:宏展科技如何定义“一个<b class='flag-5'>循环</b>”

    双向全桥(DAB)变换器的死区时间自动补偿:解决SST固态变压器在轻载下的循环电流问题

    双向全桥(DAB)变换器的死区时间自动补偿:解决以SiC模块为核心器件的SST固态变压器在轻载下的循环电流问题 1. 引言:固态变压器与双向全桥变换器的发展与挑战 在全球能源结构向可再生能源、分布式
    的头像 发表于 03-31 21:17 7241次阅读
    <b class='flag-5'>双向</b>全桥(DAB)变换器的死区时间自动补偿:解决SST固态变压器在轻载下的<b class='flag-5'>循环</b>电流问题

    功率循环基础篇(二) —— 功率循环寿命曲线解读

    功率循环寿命曲线是评估功率半导体器件(如  IGBT 模块)在温度交变应力下长期可靠性的核心工具。该曲线通常以 结温波动幅度 ΔTj 为横坐标,以器件达到指定失效判据前所经历的 循环次数 Nf 为
    的头像 发表于 03-02 11:55 345次阅读
    功率<b class='flag-5'>循环</b>基础篇(二) —— 功率<b class='flag-5'>循环</b>寿命曲线解读

    汽车热管理循环泵车规电容:-55℃~150℃宽温+1000次温度循环

    在汽车热管理循环泵中,采用 -55℃~150℃ 宽温工作能力 + 1000次温度循环 的车规电容,是保障系统在极端环境下稳定运行的核心元件。
    的头像 发表于 02-25 17:14 563次阅读

    双向保护开关评估套件使用指南

    双向保护开关评估套件使用指南 在锂离子电池的应用中,电池管理系统(BMS)起着至关重要的作用,它能监测电池状态并确保电池安全运行。其中,电子开关是BMS的重要组成部分,在关键条件下能将电池与充电器或
    的头像 发表于 12-20 20:35 1227次阅读

    双向保护开关评估套件使用指南

    双向保护开关评估套件使用指南 在锂电池应用中,电池管理系统(BMS)至关重要,它能监测电池状态并确保安全运行。BMS通常配备电子开关,在关键条件下将电池与充电器或负载断开。今天要介绍的双向开关评估
    的头像 发表于 12-20 11:10 1161次阅读

    无数据域双向链表的代码

    下面是一个简单的示例,演示了如何使用无数据域双向链表进行插入和访问操作: #include #include// 包含offsetof宏 // 定义节点结构体 struct Node
    发表于 12-11 06:56

    双向创“芯” — 云镓半导体国内首发高压 GaN 双向器件 (GaN BDS)

    云镓半导体双向创“芯”—云镓半导体国内首发高压GaN双向器件MBDS1.前言长期以来,器件工程师都在追求一种可双向导通且双向耐压的开关元件,该类器件在AC/DC、DC/AC及AC/AC
    的头像 发表于 11-11 13:43 1499次阅读
    <b class='flag-5'>双向</b>创“芯” — 云镓半导体国内首发高压 GaN <b class='flag-5'>双向</b>器件 (GaN BDS)

    rt_object_get_information获取到的链表为空怎么解决?

    rtt启动过程,在初始化堆的时候,进入rt_object_init,调用rt_object_get_information获取到的链表为空,导致系统起不来。
    发表于 10-11 11:44

    Kawaii mqtt 如何使用mbedtls双向验证?

    Kawaiimqtt如何使用mbedtls双向验证
    发表于 09-24 06:36

    人工智能行业如何使用for循环语句进行循环

    人工智能行业可以使用以下是关于for循环在不同编程语言中的基本用法说明: Python中的for循环: 主要用于遍历序列(列表、元组、字符串等) 典型结构:for item in sequence
    的头像 发表于 09-10 12:55 696次阅读

    如何实现高效双向电能变换

    随着电动汽车、家庭和工商业储能产品快速普及,双向电能变换系统的热度也在不断攀升。作为电网与电池的功率桥梁,双向电能变换系统基于一套硬件电路就能控制电池充放电,实现能量双向流动,相比传统单向变换器可大幅降低硬件成本,减小设备体积。
    的头像 发表于 07-23 11:40 1714次阅读

    Kawaiimqtt如何使用mbedtls双向验证?

    Kawaiimqtt如何使用mbedtls双向验证
    发表于 06-13 08:23

    什么是光伏双向电表?双向电表有哪些应用?

    光伏双向计量电表(Bi-directional Energy Meter) 是分布式能源系统的核心计量装置,专为光伏发电并网场景设计。与传统单向计量设备不同,该设备采用双向矢量计量技术,可精确记录
    的头像 发表于 05-12 09:42 2456次阅读
    什么是光伏<b class='flag-5'>双向</b>电表?<b class='flag-5'>双向</b>电表有哪些应用?