数据结构中的双向链表

1.链表的分类

链表的结构非常多样,以下情况组合起来就是8种(2x2x2)链表结构:

 

 在带头链表中,除了头结点,其他结点均存储有效的数据。

头结点是占位子的,也叫做“哨兵位”。head结点就是头结点。

 循环的链表尾结点不为NULL, 不循环的链表尾结点为NULL

单链表:不带头单向不循环链表

双向链表:带头双向循环链表

双向链表结构相较于单链表来说要复杂一些,但是接口的实现上要比单链表简单很多

双向链表的结点结构:数据+指向下一个结点的指针+指向前一个结点的指针

struct ListNode
{int date;struct ListNode *next;struct ListNode *prev;}

 2.双向链表的实现

2.1头结点的创建

//创建头节点
LTNode* LTBuyNode(LTDateType x)
{LTNode* newnode = (LTNode*)malooc(sizeof(LTNode);if (newnode == NULL){perror("malloc fail");exit(1);}newnode->date = x;//因为是双向循环,要循环起来,所以头结点要自己指向自己。newnode->next = newnode->prev = newnode;
}//初始化
void LTInit(LTNode** pphead)
{//创建一个头结点*pphead = LTBuyNode(-1);
}

双向链表为空的情况就是只有一个头结点

2.2插入

传的是一级指针还是二级指针要看pphead指向的结点会不会发生改变,也就是头结点会不会发生改变。

如果发生改变,那么pphead的改变要影响实参,传二级

如果不发生改变,pphead不会影响实参,传一级。

2.2.1尾插

尾插影响的是尾插前一个结点和头结点,改变他们的指向就好了。

先修改插入的结点的指向,比较方便

//插入
//传的是一级指针还是二级指针要看pphead指向的结点会不会发生改变,也就是头结点会不会发生改变。
//如果发生改变,那么pphead的改变要影响实参,传二级
//如果不发生改变,pphead不会影响实参,传一级。
//尾插
void LTPushBack(LTNode* pphead, LTDateType x)
{assert(pphead);LTNode* newnode = LTBuyNode(x);//pphead pphead->prev newnodenewnode->next = pphead;newnode->prev = pphead->prev;pphead->prev->next = newnode;pphead->prev = newnode;
}

2.2.2头插

头插是在哨兵位与第一个有效结点之间插入数据,不是在哨兵位前插入数据,在哨兵位前插入数据是尾插。

受到影响的有哨兵位,第一个有效节点,还是先改插入newnode的指向。

 

void LTPushFront(LTNode* phead, LTDateType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;}

2.3双向链表的打印

双向链表的死循环的,为了让他不死循环,结束条件可以是不等于哨兵位。

//打印
void LTprint(LTNode* phead)
{LTNode* pcur = phead->next;while (pcur!=phead){printf("%d->", pcur->date);pcur = pcur->next;}printf("\n");
}

2.4判断链表是否为空

//判断链表是否为空
bool LTEmpty(LTNode* phead)
{assert(phead);//返回true表示链表为空,返回false表示链表不为空//非0表示true,0表示false。//如果phead->next == phead,返回1//如果phead->next != phead,返回0return phead->next == phead;
}

2.5删除

不要把哨兵位删除,不会影响哨兵位,一级指针。

还要判断一下链表不为NULL,不然没东西删。

2.5.1尾删

思路:影响到的有尾结点的前一个结点以及哨兵位的结点,改变他们的指向,然后释放尾结点

void LTPopBack(LTNode* phead)
{assert(phead);//判断链表是否为NULLassert(!LTEmpty(phead));//phead prev(del->prev) del(phead->prev)LTNode* del = phead->prev;LTNode* prev = del->prev;prev->next = phead;phead->prev = prev;free(del);del = NULL;}

2.5.2头删

头删删的是哨兵位后面的结点,

//头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));//phead del(phead->next) del->nextLTNode* del = phead->next;del->next->prev = phead;phead->next = del->next;free(del);del = NULL;
}

2.6查找

//查找
LTNode* LTFind(LTNode* phead, LTDateType x)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){if (pcur->date == x){return pcur;}pcur = pcur->next;}return NULL;
}

2.7在指定位置(pos)之后插入节点

先改变newnode的指向,再改相邻的指向

 

//在指定位置(pos)之后插入节点
void LTInsert(LTNode* pos, LTDateType x)
{assert(pos);LTNode* newnode = LTBuyNode(x);//pos pos->prev pos->nextnewnode->prev = pos;newnode->next = pos->next;pos->next->prev = newnode;pos->next = newnode;}

2.8删除指定位置的结点

//删除指定位置的结点
void LTErase(LTNode* pos)
{assert(pos);//pos pos->prev pos->nextpos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;}

2.9销毁

二级指针,因为会影响到哨兵位。

从第一个有效的结点开始销毁。

//销毁
void LTDesTroy(LTNode** pphead)
{assert(pphead && *pphead);LTNode* pcur = (*pphead)->next;while (pcur!=*pphead){LTNode* Next = pcur->next;free(pcur);pcur = Next;}free(*pphead);*pphead = NULL;pcur =	NULL;}

2.10初始化和销毁也可以是一级指针

这样做的目的是为了保证接口的一致性

1.销毁的一级指针

要在.h文件中手动置为NULL

//销毁
void LTDesTroy2(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* Next = pcur->next;free(pcur);pcur = Next;}free(phead);pcur = phead = NULL;
}

2.初始化的一级指针

//初始化
LTNode* LTInit2()
{LTNode* phead = LTBuyNode(-1);return phead;
}

 第1种方法要提前弄一个plist变量,传他的地址才能调用

第二种可以直接调用。

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

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

相关文章

PPT如何添加水印?推荐两种方法!

在PPT演示文稿中添加水印,可以有效地保护版权或在背景上增加品牌标识。本文将介绍两种在PPT中添加水印的方法,帮助你轻松实现这一功能,一起来看看吧! 方法一:在单张幻灯片上添加水印 1、选择目标幻灯片 打开PPT文件&…

『深度长文』4种有效提高LLM输出质量的方法!

大家好,我是木易,一个持续关注AI领域的互联网技术产品经理,国内Top2本科,美国Top10 CS研究生,MBA。我坚信AI是普通人变强的“外挂”,专注于分享AI全维度知识,包括但不限于AI科普,AI工具测评,AI效率提升,AI行业洞察。关注我,AI之路不迷路,2024我们一起变强。 LLM,全…

docker 安装minio并配置https域名访问

一、准备目录 mkdir -p /home/minio/data/home/minio/config/home/minio/config/certs/二、下载域名证书,注意要Apache的 注意.key的换成 private.key,public.crt换成 public.crt,然后将这两个文件放到/home/minio/config/certs/目录下 三、…

贪心算法在背包问题上的运用(Python)

背包问题 有n个物品,它们有各自的体积和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? 这就是典型的背包问题(又称为0-1背包问题),也是具体的、没有经过任何延伸的背包问题模型。 背包问题的传统求解方法较为复杂,现定义有一个可以载重为8kg的背…

JNA调用DLL报堆栈溢出错误(0xC00000FD)

🏆本文收录于《CSDN问答解惑-专业版》专栏,主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收…

C++观察者模式Observer

组件协作 –(都是晚绑定的) ----观察者模式 为某些对象建立一种通知依赖的关系, 只要这个对象状态发生改变,观察者对象都能得到通知。 但是依赖关系要松耦合,不要太依赖。 eg:做一个文件分割器,需要一个…

React学习笔记(一)——react基础

1. React 介绍 1.1 React是什么 React由Meta公司研发,是一个用于 构建Web和原生交互界面的库 1.2 React的优势 相较于传统基于DOM开发的优势: 组件化的开发方式不错的性能 相较于其它前端框架的优势: 丰富的生态跨平台支持 1.3 React的市场…

基于MATLAB视觉的静态手势识别系统

一、课题介绍及思路 为了丰富手势识别方法的多样性,提高手势识别的正确率,提出了一种基于手势轮廓像素变化的手势识别方法。在Matlab环境下,设计并开发了一个基于视觉的静态手势识别系统。系统主要由两部分组成:手势分割与手势识…

数据科学已死?

既然有了人工智能,训练自己的机器学习模型是否还值得? 既然有了人工智能,学习 Python 是否还值得? 既然有了人工智能,KNIME 还在营业吗? 既然有了人工智能,数据科学是否仍然需要?…

指挥调度平台——数字赋能,让出行更有温度

智慧交通指挥调度平台是基于信息技术和智能化系统的创新解决方案,旨在提升城市交通管理效率、改善交通流畅度、减少拥堵问题,以及增强城市交通运行的智能化水平。该平台整合了大数据分析、实时监测、智能优化算法等技术,为交通管理部门提供全…

牛!6个大模型的核心技术!

大家好,我是花哥。本文我们谈下火爆的大模型背后,有哪些的核心技术! 一、Transformer Transformer 是大模型的底层模型。在深度学习的早期阶段,循环神经网络(RNN)是处理序列数据的常用方法。尽管RNN及其变…

1.XV6环境配置

安装虚拟机 这个就不多说了,搞一台Ubuntu虚拟机即可,最好是通过vscode 用ssh远程连接进行实验会比较方便,具体怎么做可参考我这篇博客: VsCode配置SSH连接远程服务器(手把手,学不会打我)_vsco…

【GitLab】使用 Docker 安装 GitLab 1:配置 SSH 端口

使用 Docker 安装 GitLab 要求修改ssh端口 GitLab 使用 SSH 通过 SSH 与 Git 交互。默认情况下,GitLab 使用端口22。 要在使用 GitLab Docker 映像时使用其他端口,您可以执行以下操作之一: 更改服务器的 SSH 端口(推荐)。 更改 GitLab Shell SSH 端口。 更改服务器的 SSH …

数据链路层 III(介质访问控制)【★★★★★】

(★★)代表非常重要的知识点,(★)代表重要的知识点。 介质访问控制所要完成的主要任务是:为使用介质的每个结点隔离来自同一信道上其他结点所传送的信号,以协调活动结点的传输。 下图所示是广播…

ubuntu安装虚拟环境(tensorflow、torch)

一、安装需求 1、确保ubuntu可以ping通百度 2、设置好了pip镜像源,(具体可看:ubuntu配pip的源-CSDN博客) 二、安装虚拟环境(务必使用sudo进行) step1:执行安装命令 更改了pip默认使用pip3的…

基于WonderJourney生成电影级连续的3D场景视频

在本文中,我将详细记录在Windows环境下配置和使用WonderJourney项目的完整流程,包括环境搭建、常见问题的解决方案以及如何修改源码以兼容Windows系统。WonderJourney项目能够生成高度逼真的村庄视频,并允许用户通过配置文件对视频生成过程进行精细化控制。 由于官方文档在…

基于Java语言的能源管理系统-水电气热油数据采集系统

介绍 基于SpringCloud的能源管理系统-能源管理平台源码-能源在线监测平台-双碳平台源码-SpringCloud全家桶-能管管理系统源码 适用于建筑、工厂、商场、医院、园区、高耗能企业、城市双碳建设平台等的水、电、气、热、油等能源数据采集、加工、分析、预警、碳指标、碳排放计算…

vue使用axios请求后端数据

前后端分离项目的基础: 前后端跨域访问 vite.config.js中加入 // 1.为什么要跨域 //因为浏览器的同源策略,不同站点之间访问需要跨域 //实现跨域的方式:server: {proxy: {// 假设要跨域访问的后端 API 地址以 /api 开头/api: { //表示拦截以/api开头的…

域名注册查询方法

域名不仅是网站的地址标识,更是企业和个人在互联网上的身份证明。要确保自己的在线品牌安全,了解域名注册查询方法至关重要。本文将介绍几种常见的域名查询方式,帮助您轻松了解网络资产的归属。 1. WHOIS查询: WHOIS(…

产品经理-​​实习中的自我迭代(41)

实习中的自我迭代,优秀实习生必备素质 跟大家认识了之后,就要开始做事情了,那我们怎么做一个优秀的实习生呢?以下几点作为参考。 1. 目标明确 知道自己的工作为什么要做,要做到什么程度,目前存在什么问题,该…