线性表的链式表示——单链表

news2025/1/11 7:46:01

目录

      • 一、单链表的定义
      • 二、单链表上基本操作的实现
        • 1、采用头插法建立单链表
        • 2、采用尾插法建立单链表
        • 3、按序号查找结点值
        • 4、按值查找表结点
        • 5、插入结点操作
        • 6、删除结点操作
        • 7、求表长操作
      • 三、双链表、循环链表、静态链表

顺序表可以随时存取表中的任意一个元素,它的存储位置可以用一个简单直观的公式表示, 但插入和删除操作需要移动大量元素链式存储线性表时,不需要使用地址连续的存储单元,即不要求逻辑上相邻的元素在物理位置上也相邻,它 通过“链”建立起数据元素之间的逻辑关系,因此 插入和删除操作不需要移动元素,而只需修改指针,但也会 失去顺序表可随机存取的优点

一、单链表的定义

线性表的链式存储又称单链表,它是指通过一组任意的存储单元来存储线性表中的数据元素。为了建立数据元素之间的线性关系,对每个链表结点除存放元素自身的信息外还需要存放一个指向其后继的指针。单链表节点结构如下图所示,其中data为数据域,存放数据元素;next为指针域,存放其后继结点的地址。
单链表结点结构
单链表中节点类型的描述如下:

typedef struct LNode{
	ElemType data;
	struct LNode *next;
}LNode,*LinkList;

利用单链表可以解决顺序表需要大量连续存储单元的缺点,但单链表附加指针域,也存在浪费存储空间的缺点。由于单链表的元素离散地分布在存储空间中,所以单链表时非随机存取的存储结构,即不能直接找到表中某个特定的结点。查找某个铁定的结点时,需要从表头开始遍历,依次查找

通常用头指针来表示一个单链表,如单链表L,头指针为NULL时表示一个空表。此外,为了操作上的方便,在单链表第一个结点之前附加一个结点,称为头结点。头结点的数据域乐意不设任何信息,也可以记录表长等信息。头结点的指针域指向线性表的第一个元素结点。

二、单链表上基本操作的实现

1、采用头插法建立单链表

该方法从一个空表开始,生成新节点,并将读取到的数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头,即头结点之后。
头插法建立单链表
头插法建立单链表的算法如下:

LinkList List_HeadInsert(LinkList &L){//头插法建立单链表
	LNode *s;int x;
	L=(LinkList)malloc(sizeof(LNode));//创建头结点
	L->next=NULL;//初始为空链表
	scanf("%d",&x);//输入要创建的结点的值
	while(x!=9999){//输出9999,停止建立单链表
		s=(Lnode*)malloc(sizeof(LNode));//创建新结点
		s->data=x;
		s->next-L->next;//将新结点插入表中,L为头指针
		L->next=s;
		scanf("%d",&x);
	}
	return L;
}

采用头插法建立单链表时,读入数据的顺序与生成的链表中的元素的元素是相反的。每个结点插入的时间为O(1),设单链表长为n,则总时间复杂度为O(n)

2、采用尾插法建立单链表

头插法建立单链表的算法虽然简单,但生成的链表中结点的次序和输入数据的顺序不一致。若希望两者次序一致,则可采用尾插法。该方法将新结点插入到当前链表的表尾,为此必须增加一个尾指针r,使其始终指向当前链表的尾结点。
尾插法建立单链表

尾插法建立单链表的算法如下:

LinkList List_TailInsert(LinkList &L){//尾插法建立单链表
	int x;
	L=(LinkList)malloc(sizeof(LNode));//创建头结点
	LNode *s,*r=L;//r为表尾指针
	scanf("%d",&x);//输入结点的值
	while(x!=9999){//输入9999停止插入
		s=(LNode*)malloc(sizeof(LNode));
		s->data=x;
		r->next=s;//在表尾插入新结点
		r=s;//r指向新结点(使r始终指向链表表尾)
		scanf("%d",&s);
	}//插入结束
	r->next=NULL;//尾结点指针置空
	return L;
}

简单易得,尾插法的时间复杂度和头插法相同,为O(n)

3、按序号查找结点值

在单链表中从第一个结点出发,顺指针next域逐个往下搜索,指导找到第i个结点为止,否则(没找到)返回最后一个结点指针域NULL。
按序号查找结点值的算法如下:

LNode *GetElem(LinkList L,int i){//按序号查找结点值
	int j=1;//计数,从1开始查找
	LNode *p=L->next;//p指向第一个结点
	if(i==0) return L;//若要查找第0个结点,返回头结点
	if(i<1) return NULL;//若i序号为无效值,返回NULL
	while(p&&j<i){//从第一个结点开始,知道找到第i个结点(j==i)
		p=p->next;
		j++;
	}
	return p;//返回第i个结点的指针,若i大于表厂,则返回NULL
}

按序号查找操作的时间复杂度为O(n)

4、按值查找表结点

从单链表的第一个结点开始,由前往后依次比较表中各结点数据域的值,若某节点数据域的值等于给定值e,则返回该结点的指针;若整个单链表中没有这样的结点,则返回NULL。
按值查找表结点的算法如下:

LNode *LocateElem(LinkList L,ElemType e){
	LNode *p=L->next;
	while(p!=NULL&&p->data!=e) p=p->next;//从第一个结点开始查找data域为e的结点
	return p;//找到后返回该结点指针,否则返回NULL
}

按值查找操作的时间复杂度为O(n)

5、插入结点操作

插入节点操作将值为x的新结点插入到单链表的第i个位置上。先检查插入位置的合法性,然后找到待插入位置的前驱结点,即第i-1个结点,再在其后插入新结点。

算法首先调用按序号查找算法GetElem(L,i-1),查找第i-1个结点。假设返回的第i-1个结点为p,然后令新结点s的指针域指向p的后继结点,再令结点p的指针域指向新插入的结点*s。其操作过程如下图所示:
插入操作

实现插入结点的代码片段如下:

p=GetElem(L,i-1);//查找插入位置的前驱结点
s->next=p->next;
p->next=s;

注意:算法中第二、三条语句的顺序不能颠倒,否则,链表断链,无法找到插入结点的后继结点。
该算法主要的时间开销在于查找第i-1个元素时间复杂度为O(n)

6、删除结点操作

删除结点操作是将单链表的第i个结点删除。先检查删除位置的合法性,后查找表中第i–1个结点,即被删除结点的前驱结点,再将其删除。其操作过程如下图所示:
删除操作
假设结点p为找到的被删结点的前驱结点,为实现这一操作的逻辑关系的变化,仅需修改p的指针域,即将p的指针域next指向p的下一个结点。实现删除结点的代码片段如下:

p=GetElem(L,i-1);//查找删除位置的前驱结点
p=q->next;//令q指向被删除结点
p->next=q->next;//将*q结点从链中断开
free(q);//释放结点的存储空间

该算法的主要时间耗费在查找操作上时间复杂度为O(n)

7、求表长操作

求表长操作就是计算单链表中数据结点(不含头结点)的个数,需要从第一个结点开始顺序依次访问表中的每个结点。设置一个计数器变量,每访问一个结点,计数器加1,直到访问到空结点为止。算法的时间复杂度为O(n)
注意:单链表的长度不包括头结点。

三、双链表、循环链表、静态链表

另有链表的其他形式讲解见文章:【待插入】

本文为个人学习总结所得,如有错误和问题欢迎指正。

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

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

相关文章

翻译:开源软件的架构(volume2): 可伸缩web框架及分布式系统

英文源地址 开源软件已经成为构建一些超大型网站的基础组成部分了.随着这些网站的成长, 围绕着它们软件架构的最佳实践与指导思想开始涌现.本文尝试去阐述设计大型网站时的需要考虑一些关键问题, 以及用于实现这些目标的基础组件. 本文主要关注web系统,尽管其中一些内容也适用于…

网络安全-01-VMware安装Kali部署DVWA

网络安全-01-VMware安装Kali&部署DVWA &#x1f53b;一、Kali简介&下载&#x1f4d7; 二、VMware安装Kali&#x1f4f0; 2.1 新建虚拟机&#x1f4f0; 2.2 开始安装Kali&#x1f4f0; 2.3 更换apt源为国内源&#x1f4f0; 2.4 启动mysql-这里使用自带的maridb&#x1f…

【Python 垃圾回收】零基础也能轻松掌握的学习路线与参考资料

Python 垃圾回收是 Python 运行机制中的重要环节。了解 Python 垃圾回收机制可帮助开发者高效编写 Python 代码&#xff0c;并避免潜在的内存泄漏问题。本文将介绍 Python 垃圾回收的学习路线&#xff0c;并给出参考资料和优秀实践。 Python 垃圾回收机制 Python 使用引用计数…

关于社会脑研究的fMRI和fNIRS超扫描方法

导读 近来&#xff0c;“社会脑”(即大脑在社会情境中是如何工作的&#xff0c;以及我们社会行为的机制是什么)在神经科学文献中获得了很多关注&#xff0c;主要是因为最近开发的技术允许研究人类社会认知的不同方面及其与大脑的关联。在这种情况下&#xff0c;超扫描技术拓宽…

如何在华为OD机试中获得满分?Java实现【质数因子】一文详解!

✅创作者:陈书予 🎉个人主页:陈书予的个人主页 🍁陈书予的个人社区,欢迎你的加入: 陈书予的社区 🌟专栏地址: Java华为OD机试真题(2022&2023) 文章目录 1. 题目描述2. 输入描述3. 输出描述4. Java算法源码5. 测试6.解题思路1. 题目描述 功能:输入一个正整数,…

vue小案例TodoList

1.首先我们分析怎么把一个页面拆成多个组件&#xff0c;如下图&#xff0c;我们可以拆成MyHeader、MyList、MyItem、MyFooter&#xff0c;其中MyList包含MyItem 2.观看如下代码&#xff08;我们把MyItem作为MyList的子组件&#xff0c;在父组件中使用v-for指令来循环展示子组件…

【java基础】Map集合

大家好&#x1f44b;&#xff0c;今天我来给大家科普一下Java中的map集合。map是Java中非常重要的数据结构之一&#xff0c;经常被用于存储键值对。 【有关这部分知识的思维导图放在文章末尾了&#xff0c;需要的C友请自取】 正文开始&#xff1a; 一、Map集合概述 我们知道&…

柱状图中最大的矩形

题目链接 柱状图中最大的矩形 题目描述 注意点 无 解答思路 暴力破解根据每根柱子x以x的高度作为矩形的高度找到其相邻能组成矩形的柱子&#xff0c;遍历所有柱子即可找到最大矩形&#xff0c;但是时间复杂度是O(n)&#xff0c;最终运行结果也超时了上面暴力破解的方法中…

MKS SERVO4257D 闭环步进电机_系列4 MODBUS指令说明

第1部分 产品介绍 MKS SERVO 28D/35D/42D/57D 系列闭环步进电机是创客基地为满足市场需求而自主研发的一款产品。具备脉冲接口和RS485/CAN串行接口&#xff0c;支持MODBUS-RTU通讯协议&#xff0c;内置高效FOC矢量算法&#xff0c;采用高精度编码器&#xff0c;通过位置反馈&am…

基于Android的视频分享平台的设计与实现

基于Android的视频分享平台的设计与实现 摘 要 短视频平台是以特定群众为目标的差异化群体定位工具。其利用自身的便捷性可以实现视频的随时拍摄和随时上传&#xff0c;可以产生亚文化圈的萌芽。这种开放便利的特性在吸引了广大用户的同时&#xff0c;也在一定程度上解决了由…

C#面试题 2

七、AOP如何在代码层面实现&#xff1f; ①静态代理实现AOP&#xff0c;自己写代理对象&#xff1b; ②动态代理实现AOP&#xff0c;运行时动态生成一个代理对象。 静态代理的实现&#xff1a;①装饰器模式&#xff08;允许向一个现有的对象添加新的功能&#xff0c;同时又不…

Doris----Rollup表分析及案例实现

ROLLUP 在多维分析中是“上卷”的意思&#xff0c;即将数据按某种指定的粒度进行进一步聚合。 之前的聚合模型: 用户id数据插入时间城市年龄性别最后一次访问的时间该用户的总消费额该用户的最大停留时长该用户的最小停留时长100002017/10/2北京1002017/10/02 08:00:00651521…

C++:STL--List

文章目录 一.STL-list的数据结构链表结点模板 二.List的框架与迭代器的实现1.STL中的容器迭代器2.List的迭代器List正向遍历迭代器类模板(对ListNode< T >* 指针的封装)反向遍历迭代器的类模板(对正向迭代器的封装) 3.List的实现框架 三. List的成员接口的实现1.在List类…

GPT-4发布!ChatGPT大升级!太太太太强了!

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 我新建了人工智能中文站https://ai.weoknow.com 每天给大家更新可用的国内可用chatGPT资源 一觉醒来&#xff0c;万众期待的GPT-4&#xff0c;它来了&#xff01; OpenAI老板Sam Altman直接开门见山地介绍说&#xff1a…

C语言之数组指针2.0

在 C 语言中&#xff0c;数组指针是一种特殊的指针类型&#xff0c;它是一个指向数组的指针。其声明形式为&#xff1a; <数据类型> (*<指针变量名>)[<数组长度>];例如&#xff0c;下面声明了一个指向整型数组的指针变量 arrPtr&#xff1a; int (*arrPtr)…

数据等级划分

数据大致可以分为定性数据与定量数据&#xff0c;但细分可以分为四类&#xff1a;定类数据、定序数据、定距数据、定比数据 处理数据的流程&#xff1a; 参考&#xff1a; 特征工程入门与实践

如何使用ChatGPT提升自己的“码”力?

如何使用chatGPT提升自己的"码"力? 代码评审(CodeReview)代码优化代码释义提供解决方案代码生成设计模式和架构建议学习新知识总结 ChatGPT是什么&#xff0c;我就不用再多介绍了吧&#xff01;相信大家已经看到了它在文本领域所展现出来的实力&#xff0c;虽然目前…

PAT A1152 Google Recruitment

1152 Google Recruitment 分数 20 作者 陈越 单位 浙江大学 In July 2004, Google posted on a giant billboard along Highway 101 in Silicon Valley (shown in the picture below) for recruitment. The content is super-simple, a URL consisting of the first 10-dig…

2023商家外卖数据

商家列表 外卖商品销量 shop_channel varchar(20) DEFAULT NULL, shop_system varchar(20) DEFAULT NULL, shop_system_no varchar(50) DEFAULT NULL, shop_platform varchar(20) DEFAULT NULL, shop_id varchar(50) NOT NULL, shop_id_str varchar(50) NO…

ChatGPT自动生成思维导图

&#x1f34f;&#x1f350;&#x1f34a;&#x1f351;&#x1f352;&#x1f353;&#x1fad0;&#x1f951;&#x1f34b;&#x1f349; ChatGPT自动生成思维导图 文章目录 &#x1f350;问题引入&#x1f350;具体操作markmapXmind &#x1f433;结语 &#x1f…