【C语言】双链表

🦄个人主页:小米里的大麦-CSDN博客

🎏所属专栏:C语言数据结构_小米里的大麦的博客-CSDN博客

🎁代码托管:黄灿灿/数据结构 (gitee.com)

⚙️操作环境:Visual Studio 2022

目录

一、什么是双链表?

二、双链表温习

1. 双链表的结构

2. 基本操作

3. 双链表讲解说明

三、代码示例(链表 · 59b38b6 · 黄灿灿/数据结构 - Gitee.com)

1. 头文件

2. 函数源文件

3. 测试代码用例

4. 小结

四、总结

共勉


一、什么是双链表?

在数据结构中,链表是一种线性数据结构,其中元素不是在内存中连续存储的,而是通过指针链接在一起。双链表是链表的一种形式,每个节点包含三个部分:一个数据字段两个指针字段,分别指向其前驱节点后继节点。这种结构允许从任意方向遍历链表。

如果提前脑海里有一定的双链表形式/样例,一定会大大帮助我们进行理解,毕竟数据结构的核心思想是图,是画图!所以,不妨看看这个:双链表 数据结构与算法c语言,完整代码动画版_哔哩哔哩_bilibili.(有一定的认识就不需要啦!)

二、深入认识双链表

1. 双链表的结构

在C语言中,双链表可以通过结构体来定义。一个典型的双链表节点结构如下:
typedef struct Node {int data; // 存储数据struct Node *prev; // 指向前一个节点struct Node *next; // 指向下一个节点
} Node;

2. 基本操作

对于双链表,我们通常需要实现以下几种基本操作:

  • 创建空链表
  • 插入节点
  • 删除节点
  • 遍历链表
  • 查找节点
  • 获取链表长度
  • 清空链表

3. 双链表讲解说明

本篇文章主要讲解的是带头双向循环链表。
带头双向循环链表: 结构最复杂 ,一般用在单独存储数据。实际中使用的链表数据结构,都是带双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。(前提是 【C语言】最详细的单链表(两遍包会!)-CSDN博客 可以手拿把掐哦!)

三、代码示例(链表 · 59b38b6 · 黄灿灿/数据结构 - Gitee.com

虽然双链表的结构相比单链表更复杂了,但正是由于双链表很“对称”,有规律,所以实现起来更方便了。

1. 头文件

#pragma once
//Double linked list:双链表#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
#include<stdbool.h>typedef struct Double_linked_list
{struct Double_linked_list* prev;int data;struct Double_linked_list* next;
}DLL;//创建一个新的节点:Create a new node
DLL* Cnew_node(int x);//初始化空的双向循环链表,返回指向头结点的指针,initialize:初始化
DLL* init_list();//打印链表内容
void print(DLL* phead);//检查链表是否为空:Check if the linked list is empty
bool empty(DLL* phead);//尾插:Tail plugging
void tail_plug(DLL* phead, int x);//头插:Header
void header(DLL* phead, int x);//在给定的位置 pos 插入一个包含 x 的新节点:Insert a new node containing x at the given location pos
void insert(DLL* pos, int x);

2. 函数源文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "Double linked list.h"//Double linked list:双链表//创建一个新的节点:Create a new node
DLL* Cnew_node(int x)
{DLL* newnode = (DLL*)malloc(sizeof(DLL));if (newnode == NULL){perror("malloc fail");//exit(-1);//如果分配内存失败,则终止程序}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}//初始化空的双向循环链表,返回指向头结点的指针,initialize:初始化
DLL* init_list()
{DLL* phead = Cnew_node(-1);phead->next = phead;phead->prev = phead;return phead;
}//打印链表内容
void print(DLL* phead)
{assert(phead);printf("<->head<->");DLL* temp = phead->next;while (temp != phead){printf("%d<->", temp->data);temp = temp->next;}printf("\n");
}//检查链表是否为空:Check if the linked list is empty
bool empty(DLL* phead)
{assert(phead);return phead->next == phead;
}//尾插:Tail plugging
void tail_plug(DLL* phead, int x)
{assert(phead);insert(phead, x);
}//头插:Header
void header(DLL* phead, int x)
{assert(phead);insert(phead->next, x);
}//在给定的位置 pos 插入一个包含 x 的新节点:Insert a new node containing x at the given location pos
void insert(DLL* pos, int x)
{assert(pos); // 确保 pos 不是 NULLDLL* prev = pos->prev; // 获取 pos 节点的前一个节点DLL* newnode = Cnew_node(x); // 创建一个包含数据 x 的新节点// 更新 prev 节点的 next 指针,使其指向新节点prev->next = newnode;// 设置新节点的 prev 指针,使其指向 prev 节点newnode->prev = prev;// 设置新节点的 next 指针,使其指向 pos 节点newnode->next = pos;// 更新 pos 节点的 prev 指针,使其指向新节点pos->prev = newnode;
}

3. 测试代码用例

#define _CRT_SECURE_NO_WARNINGS 1
#include "Double linked list.h"//Double linked list:双链表int main() {// 初始化链表DLL* list = init_list();// 测试空链表检查printf("列表是空的吗? %s\n", empty(list) ? "Yes" : "No");// 测试头插header(list, 10);header(list, 20);header(list, 30);// 打印链表内容printf("头部插入后的列表:\n");print(list);// 测试尾插tail_plug(list, 40);tail_plug(list, 50);tail_plug(list, 60);// 打印链表内容printf("尾部插入后的列表:\n");print(list);// 测试插入到指定位置insert(list->next->next, 25); // 在第二个节点之后插入25printf("在第二个元素后插入 25 后的列表:\n");print(list);// 再次检查链表是否为空printf("列表是空的吗? %s\n", empty(list) ? "Yes" : "No");// 销毁链表(注意:实际代码中应实现销毁函数)// destroy_list(list); // 假设实现了这个函数return 0;
}

4. 小结

当你看到这里的时候就会发现:双链表代码比单链表的代码会短很多,而且双链表最主要的其实就是那个插入函数,如果对上述有注释的代码还存在疑惑,不妨画一画图,会极大方便我们进行理解!如果是一头雾水,那基本上是单链表不过关,可以再回去研究研究:【C语言】最详细的单链表(两遍包会!)-CSDN博客

四、总结

在这篇文章中,我们介绍了双链表的基本概念,并展示了如何使用C语言来创建和操作双链表。双链表相比于单链表提供了更多的灵活性,因为我们可以轻松地向前或向后移动。然而,这种额外的功能也带来了更高的存储开销,因为每个节点都需要额外的指针来保存前驱节点的信息。

以上就是关于C语言中双链表的介绍,希望对你有所帮助!

共勉

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/51925.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Django开发】前后端分离django美多商城项目第2篇:展示用户注册页面,1. 创建用户模块子应用【附代码文档】

全套笔记资料代码移步&#xff1a; 前往gitee仓库查看 感兴趣的小伙伴可以自取哦~ 本教程的知识点为&#xff1a; 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计&#xff1a; 视图原型 2. 具体…

如何诱导AI犯罪-提示词注入

我们用到的大模型基本把政治类信息、犯罪相关信息都已屏蔽。但是&#xff0c;黑客依旧可以使用提示词诱导和提示词注入的方式对大模型进行攻击。 1、提示词诱导 如果直接让AI提供犯罪过程&#xff0c;AI会直接拒绝。虽然AI对于大部分知识了然于心&#xff0c;但因为经过了人工…

javase综合案例3 -- 通讯录

文章目录 一&#xff0c;项目要求基础功能拓展 二&#xff0c;导入jar包 pinyin4j.jar三&#xff0c;程序报下建立Pinyin4j类四&#xff0c;创建实体类Contact五&#xff0c;创建通讯录接口ContactDao六&#xff0c;创建ContactDao接口的视线子类ContactDaoImpl6.1 创建全局的M…

【Dash】Dash模块介绍

什么是Dash&#xff1f; Dash 是一个开源的 Python 框架&#xff0c;用于创建基于 Web 的应用程序。它由 Plotly 公司开发&#xff0c;专为数据科学家和分析师设计&#xff0c;以便他们可以构建自定义的数据可视化 Web 应用程序&#xff0c;而无需具备前端开发知识。Dash 提供…

NGINX项目实战

一、nginx四层代理 部署支持4层TCP/UDP代理的Nginx服务器 部署nginx服务器 编译安装必须要使用--with-stream参数开启4层代理模块。 [rootproxy ~]# rm -rf /usr/local/nginx/ #清理环境 [rootproxy nginx-1.16.1]# ./configure --with-http_ssl_module --with-stream #开…

Oracle特有的DECODE函数

Oracle中的DECODE函数是一种条件表达式函数&#xff0c;用于基于给定的条件从一组值中选择一个值返回。它的基本语法如下&#xff1a; DECODE(expression, search1, result1, [search2, result2, ...], [default])expression&#xff1a;要比较的表达式或列。searchN&#xff…

DDPM 核心代码解析(1)

所有代码 已上传至GitHub - duhanyue349/diffusion_model_learned_ddpm_main: 扩散模型基础框架源代码 目录结构如下 在train_cifar.py 中展示了扩散模型训练的所有代码 如果没有安装wandb 可以在create_argparser()设置 log_to_wandbFalse 一、加载模型参数 args 这里用了一…

直播圈不再只讲技术和千川,管理成为新焦点

直播圈不讲技术&#xff0c;也不讲千川啦&#xff0c;开始讲管理啦&#xff0c;感叹直播带货发展真快&#xff0c;都说要傻瓜化&#xff0c;讲的东西一年能迭代 3 个版本&#xff0c;甚至带货线下课不讲半天团队管理你的课都显得low。关键没一个能告诉你管理是什么管什么&#…

【1】CPU飙升到200%以上问题汇总

原链接 【1】CPU飙升到200%以上问题汇总 CPU飙升到200%以上是生成中常见的问题 注意&#xff1a; 1. linux的cpu使用频率是根据cpu个数和核数决定的 2. top&#xff0c;然后你按一下键盘的1&#xff0c;这就是单个核心的负载&#xff0c;不然是所有核心的负载相加&#xff0c;…

弹幕背后:B站UP主创作服务解析

引言 在B站&#xff0c;每一条飘过的弹幕都是一个故事的碎片&#xff0c;它们汇聚成一幅幅生动的社交画卷。这里&#xff0c;不仅仅是一个视频分享平台&#xff0c;弹幕背后更是一个充满活力的创作者生态系统。B站以其独特的弹幕文化&#xff0c;为创作者和观众之间搭建起了一座…

RxJava基础使用

Rx思想 事件从起点流向终点。 过程中可以对事件进行拦截&#xff0c;拦截时可以对事件进行处理&#xff0c;处理后将处理后的事件继续流向终点。 终点接收上一次处理后的事件。 获取网络图片并显示 基础实现 使用Observable.just(path) 创建图片路径的Observable。 使用m…

Unity | Shader基础知识(第二十集:应用-简易流光、LOD)

目录 一、前言 二、LOD 1.什么是LOD 2.代码如何调节LOD 三、流光 1.资源准备 2.uv移动 3.获取图片中的uv 4.改变uv去取流光的颜色&#xff08;时间的应用&#xff09; 5.图片叠加 6.透明图片的叠加 四、纯净代码 五、作者的碎碎念 一、前言 有小伙伴问&#xf…

Studying-代码随想录训练营day45| 115.不同的子序列、583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇

第45天&#xff0c;子序列part03&#xff0c;编辑距离&#x1f4aa;(ง •_•)ง&#xff0c;编程语言&#xff1a;C 目录 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离 编辑距离总结篇 115.不同的子序列 文档讲解&#xff1a;代码随想录不同的子序列 视频讲…

分布式搜索引擎ES--Elasticsearch集群

1.Elasticsearch集群的概念 分片机制&#xff1a;每个索引都可以被分片 索引my_doc只有一个主分片&#xff1b;索引shop有三个主分片&#xff1b;索引shop2有5个主分片;(参考前面案例) 每个主分片都包含索引的数据&#xff0c;由于目前是单机&#xff0c;所以副分片是没有的&a…

安全开发第一篇

文章目录 参与RASP、IAST等安全防护工具的开发技术背景开发流程技术挑战工具和资源示例结论 以phpstudydvwa为列 实现 SQL 注入检测脚本 参与RASP、IAST等安全防护工具的开发 参与 RASP&#xff08;Runtime Application Self-Protection&#xff09;和 IAST&#xff08;Intera…

为开源奉献一份自己的力量:Cesium没有热力图组件,我们自己封装!

大家好&#xff0c;我是日拱一卒的攻城师不浪&#xff0c;专注可视化、数字孪生、前端提效、nodejs、AI学习、GIS等学习沉淀&#xff0c;这是2024年输出的第27/100篇文章。 交流合作&#xff1a;brown_7778 前言 热力图&#xff0c;在很多可视化场景开发中会被经常提到&#x…

electron 主进程和渲染进程

最近在整理electron 相关的项目问题&#xff0c;对自己来说也是温故知新&#xff0c;也希望能对小伙伴们有所帮助&#xff0c;大家共同努力共同进步。加油&#xff01;&#xff01;&#xff01;&#xff01; 虽然最近一年前端大环境不好&#xff0c;但是大家还是要加油鸭&#…

网安零基础入门神书,全面介绍Web渗透核心攻击与防御方式!

Web安全是指Web服务程序的漏洞&#xff0c;通常涵盖Web漏洞、操作系统洞、数据库漏洞、中间件漏洞等。 “渗透测试”作为主动防御的一种关键手段&#xff0c;对评估网络系统安全防护及措施至关重要&#xff0c;因为只有发现问题才能及时终止并预防潜在的安全风险。 根据网络安…

【Qt开发】No matching signal for on_toolButton_clicked() 解决方案

【Qt开发】No matching signal for on_toolButton_clicked() 解决方案 文章目录 No matching signal for xxx 解决方案附录&#xff1a;C语言到C的入门知识点&#xff08;主要适用于C语言精通到Qt的C开发入门&#xff09;C语言与C的不同C中写C语言代码C语言到C的知识点Qt开发中…

Linux安装青龙面板并将本地服务映射至公网实现远程访问

文章目录 前言一、前期准备本教程环境为&#xff1a;Centos7&#xff0c;可以跑Docker的系统都可以使用。本教程使用Docker部署青龙&#xff0c;如何安装Docker详见&#xff1a; 二、安装青龙面板三、映射本地部署的青龙面板至公网四、使用固定公网地址访问本地部署的青龙面板 …