当前位置: 首页 > news >正文

【数据结构】-- 单链表 vs 双向链表

🌈 个人主页:白子寰
🔥 分类专栏:python从入门到精通,魔法指针,进阶C++,C语言,C语言题集,C语言实现游戏👈 希望得到您的订阅和支持~
💡 坚持创作博文(平均质量分82+),分享更多关于深度学习、C/C++,python领域的优质内容!(希望得到您的关注~) 

目录

 单链表和双向链表的比较

链表的打印

单链表

双向链表 

初始化

双向链表

开辟空间,写入新数据

单链表

双向链表

尾部插入数据

单链表

双向链表

头部插入数据

单链表 

双向链表

尾部删除数据

单链表

双向链表

头部删除数据

单链表

双向链表

查找

单链表 

双向链表 

在指定位置之前插入数据 

单链表

在指定位置之后插入数据

单链表

双向链表 

 删除指定位置数据

单链表

双向链表

删除指定位置后的数据

单链表

销毁链表

单链表

双向链表


 单链表和双向链表的比较

单向链表双向链表
指代不同链表的链接方向是单向的,访问链表时时要顺序读取从头开始访问每个数据的节点都有两个指针,即直接前驱和直接后驱
优点不同单个节点创建方便,普通的线性内存通常在创建的时候就需要设定数据的大小,节点的访问方便,可以通过循环/递归的方法访问到任意数据从双向链表中的任意一个节点开始,方便访问前驱节点和后继节点
缺点不同增加/删除节点复杂,需要多分配一个指针存储空间平均访问效率低于线性表,只能从头到尾遍历,只能找到后继,无法找到前驱(只能前进)

链表的打印

单链表

//链表的打印
void SLTPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}

双向链表 

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

初始化

双向链表

//双向链表初始化
LTNode* LTInit()
{//哨兵位设置为-1LTNode* phead = SLTBuyNode(-1);return phead;
}

开辟空间,写入新数据

单链表

//开辟空间,写入新数据
SLTNode* SLTbuyNode(SLTDatatype x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc");exit(1);}//先插入,后数据为空(后为空)newnode->data = x;newnode->next = NULL;return newnode;//返回数据
}

双向链表

//扩容,申请新节点
LTNode* SLTBuyNode(LTDataType x)
{LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));//扩容if (newnode == NULL){perror("malloc");exit(1);}//数据赋值newnode->dada = x;//指向自己newnode->next = newnode->prev = newnode;return newnode;
}

尾部插入数据

单链表

//尾插
void SLTPushBack(SLTNode** pphead, SLTDatatype x)
{//传的参数不为空assert(pphead);SLTNode*newnode = SLTbuyNode(x);//链表为空,新节点作为phead//*pphead是指向第一个节点的指针if (*pphead == NULL)//头节点为空{*pphead = newnode;return;}//链表不为空,找尾节点//ptail作为尾节点SLTNode* ptail = *pphead;//先方向,后数据while (ptail->next){ptail = ptail->next;}ptail->next = newnode;
}

双向链表

//尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = SLTBuyNode(x);newnode->next = phead;newnode->prev = phead->prev;phead->prev->next = newnode;phead->prev = newnode;
}

头部插入数据

单链表 

//头插
void SLTPushFront(SLTNode** pphead, SLTDatatype x)
{//传参有效assert(pphead);//开辟空间,新数据进入SLTNode* newnode = SLTbuyNode(x);//先方向,后数据newnode->next = *pphead;*pphead = newnode;
}

双向链表

//头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = SLTBuyNode(x);newnode->next = phead->next;newnode->prev = phead;phead->next = newnode;phead->prev = newnode->prev->prev;
}

尾部删除数据

单链表

//尾删
void SLTPopBack(SLTNode** pphead)
{//保证传参数据有效assert(pphead);//链表不能为空assert(*pphead);//链表不为空//链表只有一个节点if ((*pphead)->next==NULL){free(*pphead);*pphead = NULL;return;}//有多个节点SLTNode* prev = NULL;SLTNode* ptail = *pphead;while (prev->next){prev = ptail;ptail = ptail->next;}prev = NULL;//销毁尾节点free(ptail);ptail = NULL;
}

双向链表

//尾删
void LTPopBack(LTNode* phead)
{assert(phead);LTNode* del = phead->prev;del->prev->next = phead;phead->prev = del->prev;free(del);del = NULL;
}

头部删除数据

单链表

//头删
void SLTPopFront(SLTNode** pphead)
{//保证传参有效assert(pphead);//保证链表有效assert(*pphead);//让第二个节点成为新的头SLTNode* next = (*pphead)->next;//把旧的头节点释放掉free(*pphead);*pphead = next;//第一个节点 = 原来第二个节点
}

双向链表

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

查找

单链表 

SLTNode* SLTFind(SLTNode** pphead, SLTDatatype x)
{//保证传参有效assert(pphead);//遍历链表SLTNode* pcur = *pphead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}//没有找到return NULL;
}

双向链表 

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

在指定位置之前插入数据 

单链表

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDatatype x)
{//保证传参有效assert(pphead);//保证指定位置数据有效assert(pos);//链表也不能为空assert(*pphead);//新节点,开辟新空间SLTNode* newnode = SLTbuyNode(x);//pos刚好是头节点if (newnode->next = *pphead){//头插SLTPushFront(pphead, x);return;}//pos不是头节点的情况SLTNode* prev = *pphead;if (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;
}

在指定位置之后插入数据

单链表

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDatatype x)
{//保证目标数据有效assert(pos);//创建新节点SLTNode* newnode = SLTbuyNode(x);//先方向,后数据newnode->next = pos->next;pos->next = newnode;
}

双向链表 

//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = SLTBuyNode(x);newnode->prev = pos;newnode->next = pos->next;pos->next = newnode;pos->next->prev = newnode;
}

 删除指定位置数据

单链表

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{//保证传的参数有效assert(pphead);//保证单链表有效assert(*pphead);//保证目标数据有效assert(pos);//pos刚好是头节点,没有前驱节点if (*pphead == pos){//头删SLTPopFront(pphead);return;}//pos不是头节点SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//释放prev->next = pos->next;free(pos);pos = NULL;
}

双向链表

//删除pos位置的数据
void LTErase(LTNode* pos)
{assert(pos);LTNode* del = pos;pos->prev->next = pos->next;pos->next->prev = pos->prev;free(del);del = NULL;
}

删除指定位置后的数据

单链表

//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{//保证目标数据有效assert(pos);//pos->next数据有效assert(pos->next);SLTNode* del = pos->next;pos->next = pos->next->next;//释放free(del);del = NULL;
}

销毁链表

单链表

//销毁链表
void SListDesTroy(SLTNode** pphead)
{//保证传的参数有效assert(pphead);//保证链表有效assert(*pphead);SLTNode* pcur = *pphead;while (pcur){SLTNode* next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}

双向链表

//销毁
void LTDesTroy(LTNode* phead)
{//哨兵位不能为空assert(phead);LTNode* pcur = phead->next;while(pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = NULL;
}

***********************************************************分割线*****************************************************************************
完结!!!
感谢浏览和阅读。

等等等等一下,分享最近喜欢的一句话:

“成为正确答案的第一步,相信自己会是正确答案”。

我是白子寰,如果你喜欢我的作品,不妨你留个点赞+关注让我知道你曾来过。
你的点赞和关注是我持续写作的动力!!! 
好了划走吧。

相关文章:

【数据结构】-- 单链表 vs 双向链表

🌈 个人主页:白子寰 🔥 分类专栏:python从入门到精通,魔法指针,进阶C,C语言,C语言题集,C语言实现游戏👈 希望得到您的订阅和支持~ 💡 坚持创作博文…...

暴雨孙辉:做好服务器,但更要辟出技术落地之道

稳扎稳打一直是暴雨的风格,这在被访者孙辉的身上尽显。作为暴雨(武汉暴雨信息发展有限公司)中国区销售及市场副总裁,在谈及公司的技术发展与市场推广走势之时,孙辉沉稳、敏锐且逻辑清晰。 因在服务器领域起步很早&…...

天地人和•大道不孤——卢禹舜中国画作品展在重庆美术馆隆重开幕

2024年4月12日,由中国国家画院、重庆市文化和旅游发展委员会主办,重庆美术馆(重庆画院、重庆国画院)、北京八荒锦绣美术馆、中国国际文化交流基金会卢禹舜艺术基金承办的“天地人和•大道不孤——卢禹舜中国画作品展”开幕式在重庆…...

python-pytorch使用日志0.5.007

python-pytorch使用日志 1. optimizer.zero_grad()和model.zero_grad()的区别2. cbow和skip-gram的训练数据格式3. 获取cbow和skip-gram训练后的中文词向量4. 获取到词向量后可以做什么5. 余弦相似度结果的解释 1. optimizer.zero_grad()和model.zero_grad()的区别 都是清空模…...

itop4412编译内核时garbage following instruction -- `dmb ish‘ 解决方案

王德法 没人指导的学习路上磕磕绊绊太耗费时间了 今天编译4412开发板源码时报 garbage following instruction – dmb ish’ 以下是解决方案: 1.更新编译器 sudo apt-get install gcc-arm-linux-gnueabi 更新后修改Makefile 中编译器路径如下图 2.你以为更新完就可…...

(学习日记)2024.04.16:UCOSIII第四十四节:内存管理

写在前面: 由于时间的不足与学习的碎片化,写博客变得有些奢侈。 但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。 既然如此 不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录&a…...

微信小程序Skyline模式下瀑布长列表优化成虚拟列表,解决内存问题

微信小程序长列表,渲染的越多就会导致内存吃的越多。特别是长列表的图片组件和广告组件。 为了解决内存问题,所以看了很多人的资料,都不太符合通用的解决方式,很多需要固定子组件高度,但是瀑布流是无法固定的&#xf…...

大语言模型LLM《提示词工程指南》学习笔记03

文章目录 大语言模型LLM《提示词工程指南》学习笔记03链式提示思维树检索增强生成自动推理并使用工具自动提示工程师Active-Prompt方向性刺激提示Program-Aided Language ModelsReAct框架Reflexion多模态思维链提示方法基于图的提示大语言模型LLM《提示词工程指南》学习笔记03 …...

239. 奇偶游戏(带权值并查集,邻域并查集,《算法竞赛进阶指南》)

239. 奇偶游戏 - AcWing题库 小 A 和小 B 在玩一个游戏。 首先,小 A 写了一个由 0 和 1 组成的序列 S,长度为 N。 然后,小 B 向小 A 提出了 M 个问题。 在每个问题中,小 B 指定两个数 l 和 r,小 A 回答 S[l∼r] 中…...

程序员做副业,AI头条,新赛道

大家好,我是老秦,6年编程,自由职业3年,今天继续更新副业内容。 在当今信息爆炸的时代,副业赚钱已成为许多人增加收入的重要途径。其中,AI头条模式以其独特的优势,吸引了越来越多的写作者加入。…...

Redis: 内存回收

文章目录 一、过期键删除策略1、惰性删除2、定时删除3、定期删除4、Redis的过期键删除策略 二、内存淘汰策略1、设置过期键的内存淘汰策略2、全库键的内存淘汰策略 一、过期键删除策略 1、惰性删除 顾名思义并不是在TTL到期后就立即删除,而是在访问一个key的时候&…...

【刷题篇】回溯算法(三)

文章目录 1、全排列2、子集3、找出所有子集的异或总和再求和4、全排列 II5、电话号码的字母组合6、括号生成 1、全排列 给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 class Solution { public:vector<vector<i…...

pe格式从入门到图形化显示(八)-导入表

文章目录 前言一、什么是Windows PE格式中的导入表&#xff1f;二、解析导入表并显示1.导入表的结构2.解析导入表3.显示导入表 前言 通过分析和解析Windows PE格式&#xff0c;并使用qt进行图形化显示 一、什么是Windows PE格式中的导入表&#xff1f; 在Windows中&#xff0…...

如何将Paddle(Lite)模型转换为TensorFlow(Lite)模型

模型间的相互转换在深度学习应用中很常见&#xff0c;paddlelite和TensorFlowLite是移动端常用的推理框架&#xff0c;有时候需要将模型在两者之间做转换&#xff0c;本文将对转换方法做说明。 环境准备 建议使用TensorFlow2.14&#xff0c;PaddlePaddle 2.6 docker pull te…...

最新Zibll子比主题V7.1版本源码 全新推出开心版

源码下载地址&#xff1a;Zibll子比主题V7.1.zip...

响应式布局(其次)

响应式布局 一.响应式开发二.bootstrap前端开发框架1.原理2.优点3.版本问题4.使用&#xff08;1&#xff09;创建文件夹结构&#xff08;2&#xff09;创建html骨架结构&#xff08;3&#xff09;引入相关样式&#xff08;4&#xff09;书写内容 5.布局容器&#xff08;已经划分…...

arhtas idea plugin 使用手册

arthas idea plugin 使用文档 语雀...

数组算法——查询位置

需求 思路 使用二分查找找到第一个值&#xff0c;以第一个值作为界限&#xff0c;分为左右两个区间在左右两个区间分别使用二分查找找左边的7,&#xff1a;找到中间位置的7之后&#xff0c;将中间位置的7作为结束位置&#xff0c;依次循环查找&#xff0c;知道start>end,返回…...

【解决leecode打不开的问题】使用chrome浏览器和其他浏览器均打不开leecode

问题描述&#xff1a; 能进入leetcode力扣官网但是对某些栏目加载不出来&#xff0c;比如学习栏目能完成加载、题库栏目不能加载。 解决方法一&#xff1a;cookies缓存问题 首先尝试删除浏览器cookie缓存。 因为以下原因&#xff1a; Cookies损坏或过期&#xff1a;有些网站…...

尝试在手机上运行google 最新开源的gpt模型 gemma

Gemma介绍 Gemma简介 Gemma是谷歌于2024年2月21日发布的一系列轻量级、最先进的开放语言模型&#xff0c;使用了与创建Gemini模型相同的研究和技术。由Google DeepMind和Google其他团队共同开发。 Gemma提供两种尺寸的模型权重&#xff1a;2B和7B。每种尺寸都带有经过预训练&a…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

三分算法与DeepSeek辅助证明是单峰函数

前置 单峰函数有唯一的最大值&#xff0c;最大值左侧的数值严格单调递增&#xff0c;最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值&#xff0c;最小值左侧的数值严格单调递减&#xff0c;最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制&#xff0c;重点解析"道作为序位生成器"的核心原理与实现框架&#xff1a; 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

深入理解 React 样式方案

React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...