数据结构与算法中的双向链表
链表概念在现实世界中使用得很普遍。当我们使用 Spotify 播放队列中的下一首歌曲时,我们学到的单链表的概念就开始发挥作用。但是要播放队列中的上一首歌曲到底可以做什么呢?
在这篇博客中,我们将了解与数据结构相关的另一个概念,即双向链表。我们还将讨论使用 C 语言和实时应用程序的实现。
什么是双向链表?
链表是一种线性数据结构,包含以顺序方式连接的节点。该节点包含三个字段,即存储在该参考地址处的数据和指向该参考节点左侧和右侧的后继节点的两个指针。
左节点指针存储序列中前一个节点的内存地址,右节点存储下一个节点的内存地址。我们在这里使用动态内存分配而不是数组,以便可以在运行时根据执行的操作分配或取消分配内存大小。

在这个例子中,头指向第一个节点。引用节点的左指针存储NULL,最后一个节点的右指针也是如此。
为了对这个例子进行操作,我们可以进一步进行相应的更改。
双向链表的实现
1、在前面插入节点
为了完成上述操作,首先创建一个节点并使用动态内存分配内存。将头指向新节点,并在左节点和右节点中存储 NULL 值。
void front_add(){//allocate memory using dynamic memory allocation.newnode -> data = NULL;newnode -> prev = NULL;newnode -> next = head;head= newnode;
}
2.删除最前面的节点
要从前面删除节点,我们必须将引用地址的正确节点值存储在头部并释放第一个节点。
void front_del(){newnode=head;head= head->next ;head->prev = NULL;free(newnode);
}
3. 在末尾插入节点
要在末尾添加节点,我们必须遍历到末尾并将最后一个节点指向引用的新节点,反之亦然。
void end_add(){//allocate memory to newnodenewnode -> data= item; // temp=headwhile(temp ->next !=NULL){temp = temp->next;}temp->next= newnode;newnode -> prev = temp;newnode-> next = NULL;}
4.删除末尾节点
要删除末尾的节点,我们必须遍历链表并到达末尾。我们将使用指向最后一秒节点的指针。然后释放最后一个节点。
void rear_del(){while(temp -> next!=NULL){temp = temp->next; //temp=head}temp ->prev-> next = NULL;free(temp);
}
现在我们已经了解了基本操作,现在我们将逐步使用 C 实现双向链表。
#include<stdio.h>
#define MAX 5struct node{int data;struct node * prev;struct node * next;
};
struct node *head;
void front_add();
void front_del();
void rear_add();
void rear_del();
void display();int main(){int choice=0;while(choice!=6){printf("enter choice:\n");printf("\n1.front_add\n2.front_Del\n3.rear_add\n4.rear_del\n5.display\n6.exit");scanf("%d\n",&choice);switch(choice){case 1:front_add();break;case 2:front_del();break;case 3:rear_add();break;case 4:rear_del();break;case 5:display();break;case 6:printf("exiting...\n");break;default:printf("unknown choice\n");}}
}
void front_add(){struct node* newnode;int item;newnode = (struct node*)malloc(sizeof(struct node));printf("enter item value:\n");scanf("%d", &item);if(head == NULL){newnode -> next = NULL;newnode -> prev = NULL;newnode -> data = item;head = newnode;}else{newnode -> data = item;newnode -> prev = NULL;newnode -> next = head;head->prev = newnode;head= newnode;}
}
void front_del(){struct node *newnode;if(head->next == NULL){head = NULL;free(head);printf("\nnode deleted\n");}else{newnode=head;head= head->next ;head->prev = NULL;free(newnode);printf("deleted\n");}
}
void rear_add(){struct node *temp,*newnode;int item;newnode = (struct node*)malloc(sizeof(struct node));printf("enter item");scanf("%d", &item);newnode -> data= item;temp = head;while(temp ->next !=NULL){temp = temp->next;}temp->next= newnode;newnode -> prev = temp;newnode-> next = NULL;printf("inserted\n");}
void rear_del(){struct node *temp;temp=head;if(head->next==NULL){head = NULL;free(head);printf("deleted\n");}else{while(temp -> next!=NULL){temp = temp->next;}temp ->prev-> next = NULL;free(temp);printf("deleted\n");}
}
void display(){struct node *temp;temp = head;if(head==NULL){printf("empty\n");}else{while(temp!=NULL){printf("%d", temp->data);temp = temp->next;}}
}
此代码将为您提供所需的输出:

您有没有想过这些多人游戏是如何开发的,玩家可以在重复的循环中获得机会?这意味着最后一个玩家再次链接到第一个玩家以形成循环。
为了使这成为可能,我们引入了另一个与链表相关的概念。在这种情况下,循环链表很有用。
循环链表
在循环单链表中,链表的最后一个节点包含指向链表第一个节点的指针。双链表和单链表都可以使用这个概念。
该列表与其他两个列表的唯一区别是最后一个节点的右指针指向第一个节点,而头节点始终指向第一个节点本身。

结论
在我看来,链表的概念在解决复杂问题时非常重要和有用。在经历各种场景时,双向链表和循环单链表都是齐头并进的。我希望您喜欢阅读这个博客。请点赞并评论您对今天主题的看法。学习愉快!!
相关文章:
数据结构与算法中的双向链表
链表概念在现实世界中使用得很普遍。当我们使用 Spotify 播放队列中的下一首歌曲时,我们学到的单链表的概念就开始发挥作用。但是要播放队列中的上一首歌曲到底可以做什么呢? 在这篇博客中,我们将了解与数据结构相关的另一个概念,…...
数据安全治理的关键-数据分类分级工具
强大的资产发现能力 多种资产发现方式的组合应用,能够最大程度地提高资产发现能力。 灵活的敏感数据分类分级规则 内置丰富的敏感数据分类分级规则,支持正则表达式、关键词组、非结构化指纹、结构化指纹、机器聚类等多种匹配方式,并且规则…...
Spring集成Junit
目录 1、简介 2、Junit存在的问题 3、回顾Junit注解 4、集成步骤 4.1、导入坐标 4.2、Runwith 4.3、ContextConfiguration 4.4、Autowired 4.5、Test 4.6、代码 5、补充说明 5.1、Runwith 5.2、BlockJUnit4ClassRunner 5.3、没有配置Runwith ⭐作者介绍࿱…...
Java正则校验密码至少包含:字母数字特殊符号中的2种
一、语法 字符说明\将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, n匹配字符 n。\n 匹配换行符。序列 \\\\ 匹配 \\ ,\\( 匹配 (。^匹配输入字符串开始的位置。如果设置了 RegExp 对象的 Multiline 属性,^ 还会与"\n…...
Stable Diffusion教程(6) - 扩展安装
打开stable diffusion webUI界面 加载插件列表 依次点击扩展->可用->加载自 搜索插件 首先在搜索框输入你要安装的插件,然后点击插件后面的安装按钮 如果你需要的插件这里面没有找到,可通过通网址安装的方式安装。 在git仓库网址输入框输入的你插件…...
Jenkins通过OpenSSH发布WinServer2016
上一篇文章> Jenkins集成SonarQube代码质量检测 一、实验环境 jenkins环境 jenkins入门与安装 容器为docker 主机IP系统版本jenkins10.10.10.10rhel7.5 二、OpenSSH安装 1、下载 官网地址:https://learn.microsoft.com/zh-cn/windows-server/administration/op…...
字母异位词分组 LeetCode热题100
题目 给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词 是由重新排列源单词的所有字母得到的一个新单词。 思路 将字符串按字符升序排列后作为key,原字符串作为value存储到map上。 代码 class Solution…...
使用angular和electron 构建桌面应用
使用angular和electron 构建桌面应用 初始设置 新建一个angular app npm install -g @angular/cli ng new angular-electron cd angular-electron修改src/index.html文件内容 将绝对路径改为相对路径,加个点,使electron可以访问到angular文件资源 <base href=".…...
安达发制造工业迈向智能化:APS高级计划排程助力提升生产效率
随着市场竞争的加剧,制造企业纷纷寻求提高生产效率和降低成本的方法。近年来,越来越多的制造企业开始采用APS(高级计划与排程)系统,以优化生产计划和排程,提高生产效率,并在竞争中取得优势。 现代制造业通常面临复杂的…...
Flink - sink算子
水善利万物而不争,处众人之所恶,故几于道💦 文章目录 1. Kafka_Sink 2. Kafka_Sink - 自定义序列化器 3. Redis_Sink_String 4. Redis_Sink_list 5. Redis_Sink_set 6. Redis_Sink_hash 7. 有界流数据写入到ES 8. 无界流数据写入到ES 9. 自定…...
【项目 线程2】3.5 线程的分离 3.6线程取消 3.7线程属性
3.5 线程的分离 #include <stdio.h> #include <pthread.h> #include <string.h> #include <unistd.h>void * callback(void * arg) {printf("chid thread id : %ld\n", pthread_self());return NULL; }int main() {// 创建一个子线程pthread…...
Filebeat+ELK 部署
目录 //在 Node1 节点上操作 1.安装 Filebeat 2.设置 filebeat 的主配置文件 3.在 Logstash 组件所在节点上新建一个 Logstash 配置文件 4.浏览器访问 http://192.168.193.40:5601 登录 Kibana,单击“Create In…...
el-table点击表格某一行添加到URL参数,访问带参URL加载表格内容并滚动到选中行位置 [Vue3] [Element-plus 2.3]
写在最前 需求:有个表格列出了一些行数据,每个行数据点击后会加载出对应的详细数据,想要在点击了某一行后,能够将该点击反应到URL中,这样我复制这个URL发给其他人,他们打开时也能看到同样的行数据。 url会根…...
【树】 二叉树 堆与堆排序 平衡(AVL)树 红黑(RB)树
目录 1 树1.1 认识树1.2 树的相关概念1.3 树的表示孩子兄弟表示法 2 二叉树2.1 概念2. 2 特殊二叉树2.3 二叉树的性质2.4 二叉树的存储结构 3 堆 — 完全二叉树的顺序结构实现3.1 堆的概念3.2 核心代码3.3 堆应用1 堆排序2 TOP-K问题 4 二叉树的链式存储4.1 二叉链结构与初始化…...
信号平滑或移动平均滤波研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
黑客技术(网络安全)自学
一、黑客是什么 原是指热心于计算机技术,水平高超的电脑专家,尤其是程序设计人员。但后来,黑客一词已被用于泛指那些专门利用电脑网络搞破坏或者恶作剧的家伙。 二、学习黑客技术的原因 其实,网络信息空间安全已经成为海陆空之…...
使用七牛云、阿里云、腾讯云的对象存储上传文件
说明:存在部分步骤省略的情况,请根据具体文档进行操作 下载相关sdk composer require qiniu/php-sdkcomposer require aliyuncs/oss-sdk-php composer require alibabacloud/sts-20150401composer require qcloud/cos-sdk-v5 composer require qcloud_s…...
使用阿里云DataX完成数据同步
DataX DataX 是阿里云 DataWorks 数据集成的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS, datab…...
《Kali渗透基础》13. 无线渗透(三)
kali渗透 1:无线通信过程1.1:Open 认证1.2:PSK 认证1.3:关联请求 2:加密2.1:Open 无加密网络2.2:WEP 加密系统2.3:WPA 安全系统2.3.1:WPA12.3.2:WPA2 3&#…...
python——案例六:判断字符串的长度
案例六:判断字符串的长度str"Study"print(len(str))#输出结果如下: #5...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
排序算法总结(C++)
目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指:同样大小的样本 **(同样大小的数据)**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
