数据结构:线性表的链式表示和实现

news2025/4/12 8:17:23

顺序表仅适用于不常进行插人和删除的线性表。因为在顺序存储表示的线性表中插入或删除一个数据元素,平均约需移动表中一半元素,这个缺陷是由于顺序存储要求线性表的元素依次“紧挨”存放造成的。因此对于经常需要进行插人和删除操作的线性表,就需要选择其他的存储表示方法。现在我们讨论线性表的另一种表示方法——链式存储表示,由于它不要求逻辑上“相邻”(例如ai和ai+1)的两个数据元素在存储位置上也“相邻”,因此它没有顺序存储结构所具有的弱点,但同时也失去了顺序表可随机存取的优点。

一、单链表和指针

线性表的链式存储表示的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的)。因此,为了表示每个数据元素 ai与其直接后继数据元素 a i+1之间的逻辑关系,对数据元素 ai来说,除了存储其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。这两部分信息组成一个“结点”表示线性表中一个数据元素 ai。结点中存储数据元素信息的域称为数据域(设域名为data),存储直接后继存储位置的域称为指针域(设域名为 next)。指针域中存储的信息又称做指针。上述结点结构如图 2.6 所示。N 个结点(分别表示 a1,a2, ..... ,an)依次相链构成一个链表,称为线性表的链式存储表示,由于此类链表的每个结点中只包含一个指针域,故又称单链表或线性链表。

例如图 2.7 所示为线性表

(ZHAO,QIAN,SUN,LI, ZHOU,WU,ZHENG,WANG) 的单链表。

图2.7中H为 一“指针”变量,它的值为第一个结点的存储位置,第一个结点中的“指针”指向第二个结点,即它的值为第二个结点的存储位置,第二个结点中的“指针”指向第三个结点....,以此类推,直至最后一个结点。因为线性表的最后一个数据元素没有后继,因此最后一个结点中的“指针”是一个特殊的值“NULL"(在图上用^表示),通常称它为“空指针”。整个链表中的各个结点,即线性表的各个数据元素均可从指针H出发找到,称H为链表的“头指针”。在链表中,“结点”和“指针”是相互紧密关联的两个概念,需用C语言中的“结构指针”来描述。

下面先介绍有关“指针”的几个基本操作的含义.

若设 LNode *p,*q;

LinkList H;

则 p,q 和 H 均为以上定义的指针型变量。若 p 的值非空,则表明 p 指向某个结点,p->data表示 p 所指结点中的数据域,p->next 表示 p 所指结点中的指针域;若非空,则指向其“后继”结点。

指针型变量只能作同类型的指针赋值与比较操作。并且,指针型变量的“值”除了由同类型的指针变量赋值得到外,都必须用 C 语言中的动态分配函数得到。例如,p=new LNode; 表示在运行时刻系统动态生成了一个 LNode 类型的结点,并令指针 p“指向”该结点。反之,当指针 p 所指结点不再使用,可用 delete p; 释放此结点空间。图 2.8 展示了若干种指针赋值语句以及这些语句执行前后指针值的变化状况。

二、单链表的基本操作

1.求线性表的长度

在顺序表中,线性表的长度是它的一个属性,因此很容易求得。但当以链表表示线性表时,整个链表由一个“头指针”来表示,线性表的长度即链表中的结点个数,只能通过“遍历’链表来得到。由此,需设一个指针 p 顺链向后扫描,同时设一个整型变量k随之进行“计数”。p 的初值为指向第一个结点,k 的初值为 0。若 p不空,则k增 1,令 p 指向其后继,如此循环直至 p 为“空”止,此时所得 k 值即为表长。

具体程序如下:

若 L 为空表,p 的初值为“NULL”,算法中 while 循环的执行次数为 0,则返回 k的值(即链表长度)为 0。显然,此算法的时间复杂度为 O(n),其中 n 为表长。

2.查找元素操作

在链表 L 中查找和给定值 e 相等的数据元素的过程和顺序表类似,从第一个结点起依次和 e 相比较,直至找到一个其值和 e 相等的元素,则返回它在链表中的“位置”;或者查遍整个链表都不存在这样的一个元素后,返回“NULL”。同样,在算法中,设置了一个指针变量 p 顺链扫描,直至 p 为“NULL”,或者 p->data 和 e 相同为止。

具体程序如下:

3.插入结点操作

由于在链表中不要求两个互为“前驱”和“后继”的数据元素紧挨存放,则在链表中插人一个新的数据元素时,不需要移动数据元素,而只需要在链表中添加一个新的结点,并修改相应的指针链接。

假设在链表中指针 p 所指结点之后插人一个指针 s 所指的结点,则只需分别修改指针p 和 s 所指结点的指针域的指针即可。用 C 语言描述为:

s->next=p->next; // s 结点的“后继”应是 p结点的“后继”

p->next= s; //插入之后,p结点的“后继”应为 s 结点

通常称这种插人为“后插”,后插操作前、后链表状态变化如图 2.9 所示。

假设在链表中 p 结点之前插人一个 s 结点。此时,除了要修改 s 结点的指针域之外,还需要修改 p 的前驱结点的指针域,因为实现插入之后,p 结点不再是它“前驱”的“后继”,它“前驱”的“后继”应该是 s 结点。通常称这种插人为“前插”。一般情况下前插操作前、后链表状态变化如图 2.10 所示。假设指针 q 指向 p 结点的前驱结点,则描述“前插”修改指针的C语句为:

q-> next= s; // q结点的后继修改为 s 结点

s->next=p; //p结点修改为 s 结点的后继

可见,实现“前插”操作首先应该找到它的前驱结点,这只要从链表的头指针起进行查找即可。令 q 的初值等于头指针,查找结束的条件是 q->next==p;若否,则指针 q 后移。还有一点要注意的是,如果 p 所指结点是链表中的第一个结点,则“前插”操作尚需修改链表的头指针。

具体程序如下:

上述算法中,假定 p 确实指向链表中的某个结点,因此在查找其前驱结点时,不考虑查找不到的情况。

从以上两种插入操作的讨论可知,在链表中已知结点之后插入新的结点时,不需要进行查找。因此“后插”操作的时间复杂度为 O(1)。而在链表中已知结点之前进行插入时,虽然修改指针的时间是个常量,但由于需查找它的前驱,因此,“前插”操作的时间复杂度为O(n),其中n 为链表的长度。

4.删除结点操作

和插入类似,在链表中删除一个结点时,也不需要移动元素,仅需修改相应的指针链接。但由于删除结点时,需要修改的是它的“前驱”结点的指针域,因此和“前插”操作一样,首先应该找到它的前驱结点。如图 2.11 所示,假设待删除的是指针 p 所指结点,指针 q 指向它的前驱,则删除 p 结点将改变其前驱和后继的关系,q结点的后继不再是 p 结点,而应该是p 结点的后继,则应修改 q 结点的指针域,令它指向 p 结点的后继,即实现 q->next=p->next。同样,假如 p 结点是链表中的第一个结点,则尚需修改链表的头指针。

具体程序如下:

和前面讨论的前插类似,在上述算法中,假定 p 确实指向链表中的某个结点,因此在查找其前驱结点时,不考虑查找不到的情况。

容易看出,算法的时间复杂度亦为 O(n),其中 n 为链表的长度。

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

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

相关文章

C进阶:文件的基础操作

本文主要讲解文件基础操作的知识。 目录 一.文件指针 二.文件的打开和关闭 1.文件的打开 打开文件我们需要使用到 fopen 函数; 注意(文件扩展名): 2.文件的关闭 三.文件的读写 1.读与写,输出与输入的概念 ​编…

VueUse(中文)——简介

一、VueUse——简介 VueUse是由Anthony Fu等大佬写的基于Vue的自定义钩子集合。类似于基于React的 ahooks功能丰富:200功能无缝迁移:适用于Vue 3和Vue2.7版本之后支持tree shaking:只引入自己需要的那部分,打包会更小还有其他的亮…

Chrome V3版开发教程使用Vue 3.x+Ant构建项目

简介 ​ Google在2023年将会遗弃V2版本,而目前在CSDN平台上的大部分Chrome插件的开发教程都是基于V2版本的,V3版本和V2的版本上还是有很大的区别,就比如manifest.json中的写法差距就很大,所以对于即将要开发Chrome插件的小伙伴来…

机器学习的相关概念与建模流程

文章目录一、机器学习简介1. 机器学习的相关定义2. 一次简单的机器学习任务:鸢尾花分类二、数据与数据集相关概念1. 数据与数据集2. 特征与标签3. 连续变量和离散变量4. 模型类型三、机器学习建模一般流程1. 提出基本模型2. 确定损失函数3. 根据损失函数性质&#x…

Servlet —— Smart Tomcat,以及一些访问出错可能的原因

JavaEE传送门JavaEE HTTPS —— HTTPS的加密方式 Servlet —— Tomcat, 初学 Servlet 程序 目录Smart TomcatSmart Tomcat 的下载配置 Smart Tomcat 插件访问出错404405500无法访问此网站Smart Tomcat 在上一篇文章中, 我们手动拷贝 war 包到 Tomcat 中的过程比较麻烦, 我们…

解析 json,整理分散数据入库

【问题】在 json 文件中有以下内容:现在需要将 json 中分散的数据整理入库。“LIST”中包含多个子孙记录,主要目标是”GROUPNAME”、”SERVICES”。“GROUPNAME”值、”SERVICES”中的键编号对应了数据库表 _groups 的 Groupname 和 ID。“SERVICES”每个…

PicGo+Gitee+Typora实现markdown图床

PicGoGitee实现markdown图床 情景概要 写博客的时候,总是需要插入图片的,图片存在本地的话上传到博客网站去就没法显示了 就算一个图一个图的复制粘贴上去,想移植到其他的博客网站,图就会失效,我们就需要图床 图床 …

系分 - 案例分析 - 项目管理

个人总结,仅供参考,欢迎加好友一起讨论 文章目录系分 - 案例分析 - 项目管理时间管理进度管理典型例题题目描述参考答案系分 - 案例分析 - 项目管理 时间管理 进度管理 ① 项目进度管理包括为管理项目按时完成所需的7个过程,具体为&#xf…

MyBatis-Plus数据安全保护(字段脱敏)

项目创建POM依赖 <dependency><!--MyBatis-Plus 企业级模块--><groupId>com.baomidou</groupId><artifactId>mybatis-mate-starter</artifactId><version>1.2.8</version> </dependency> YML配置 spring:datasource:# 配…

熟悉Spring框架?Spring容器使用流程,注解 你真的会吗?(让你一下通透~)

目录 前言 一、ApplicationContext 和 BeanFactory 的区别 二、主要工作流程 三、开发步骤 3.1、创建Maven项目 3.2、创建Spring的核心配置文件 3.3、Spring注解 3.3.1、类注解 3.3.2、五大类注解的关系 3.3.3、方法注解 3.3.4、属性注入 3.3.5、五大注解关系图&am…

【03】FreeRTOS的任务创建(静态和动态)和删除

目录 1.任务创建和删除的API函数 1.1动态创建任务函数 1.1.1实现动态创建任务流程 1.1.2任务控制块结构成员介绍 1.2静态创建任务函数 1.2.1实现静态创建任务流程 1.3任务删除函数 1.3.1删除任务流程 2.任务创建和删除&#xff08;动态方法&#xff09; 2.1宏confi…

一文掌握项目估算工具及方法【管理有度13】

01为什么要做估算我们的业务方经常抱怨资源不足&#xff0c;团队需求的吞吐率太低&#xff0c;资源和需求量的不匹配是一个永恒的话题&#xff0c;解决方案应该不只是增加资源&#xff0c;增加了资源如果需求的输入量不能稳定保证&#xff0c;那资源就会处于持续浪费的状态当中…

项目管理:项目控制的三个基本原则

要记住项目控制是怎么回事&#xff0c;一个简单方法是思考PDA。PDA是指预防、检测和行动。让我们仔细看看项目控制的这些基本原则。 1、预防 就像你自己的健康一样&#xff0c;健康的秘诀是加强你的免疫系统&#xff0c;尽量减少与有害物的接触。换句话说&#xff0c;就是不…

谷歌账号被封怎么办?谷歌账号解封申诉步骤请收好!

谷歌账号有多重要&#xff1f;相信很多跨境人和社媒营销人都会深有感悟的&#xff0c;谷歌账号可以说是国外互联网的一个通行证&#xff0c;国外非常多的网站都是支持使用谷歌账号登录的。 谷歌账号对企业进军海外市场是非常重要的存在&#xff0c;然而谷歌账号一旦操作不当是很…

Go语言变量

Go语言变量 参考资料主要来源于菜鸟教程。 参考链接&#xff1a;https://blog.51cto.com/u_15230485/2821028 变量来源于数学&#xff0c;是计算机语言中能存储计算结果或能表示值抽象概念。 变量可以通过变量名访问。 Go语言变量名由字母、数字、下划线组成&#xff0c;其中首…

Vector和ArrayList对比

本文会对ArrayList和Vector进行分析&#xff0c;为什么会关注这两个类&#xff0c;主要是因为他们拥有相同的继承结构&#xff0c;接下来就来探索下这两个类实现和效率的异同。 继承结构 可以看到&#xff0c;Vector和ArrayList都实现了List和RandomAccess接口&#xff0c;都继…

C语言——常用字符串库函数的介绍

文章目录常用字符串库函数介绍1.1关于字符串简介1.2:[strlen库函数](https://legacy.cplusplus.com/reference/cstring/strlen/?kwstrlen)1.2.1strlen函数的功能1.2.2strlen函数的参数和返回类型1.2.3strlen函数使用注意事项1.2.4strlen的使用1.2.5模拟实现strlen函数1.3:[str…

喜讯!酷开科技荣获中国国际广告节三项殊荣!

近日&#xff0c;由中国广告协会主办的第29届中国国际广告节AD Fair媒企交易会在厦门国际会展中心隆重举行。其中备受瞩目的三大盛典&#xff1a;广告主金伙伴盛典、广告主盛典、媒企盛典&#xff0c;是广告业必不可少的荣誉殿堂&#xff0c;他们不仅是对中国广告传媒业各方主体…

【C++升级之路】第七篇:STL简介

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;从整体上对STL进行粗略介绍 &#x1f6a2;&#x1f6a2;作者简介&#xff1a;计算机海洋的新进船长一枚&…

GTD之初总结

思维导图 GTD&#xff1a;GTD是“Getting Things Done”的缩写&#xff0c;是由效率管理专家戴维艾伦&#xff08;David Allen&#xff09;开创的一套完整个人时间管理系统 既高效地处理工作事务&#xff0c;又能品味生活的快乐滋味&#xff0c;达到心如止水的轻松感 GTD工作…