线性表——(3)线性表的链式存储及其运算的实现

一、前言:

        由于顺序表的存储特点是用物理上的相邻关系实现逻辑上的相邻关系,它要求用连续的存储单元顺序存储线性表中各数据元素,因此,在对顺序表进行插入、删除时,需要通过移动数据元素来实现,这影响了运行效率。本节介绍线性表的链式存储结构,它不需要用地址连续的存储单元来实现,因为它不要求逻辑上相邻的两个数据元素在物理上也相邻。在链式存储结构中,数据元素之间的逻辑关系是通过“”来连接的,因此对线性表的插入、删除不需要移动数据元素

二、单链表: 

        链表是通过一组任意的存储单元来存储线性表中的数据元素的,那么怎样表示数据元素之间的线性关系呢?即如何来“链”接数据元素间的逻辑关系呢?为此,在存储数据元素时,对于每个数据元素ai,除了存放数据元素的自身信息 ai,还需要和 ai一起存放其后继数据元素 ai+1 所在的存储单元的地址,这两部分信息组成一个节点,节点的结构如图 A所示,每个数据元素皆是如此。存放数据元素自身信息的单元称为数据域存放其后继数据元素地址的单元称为指针域因此n个数据元素的线性表通过每个节点的指针域拉成了一个“链子”,称为链表。图A 所示链表的每个节点中只有一个指向后继的指针,所以称其为单链表

图A  单链表节点的结构

链表是由节点构成的,节点定义如下: 

typedef struct LNode{
	datatype data;//存放数据元素 
	struct LNode *next;//存放下一个节点的地址 
}LNode,*LinkList;

定义头指针变量:

LinkList h;//定义头指针变量

图B 所示为线性表 (a1, a2, a3, a4, a5, a6, a7, a8)对应的链式存储结构示意图。 

图B 链式存储结构示意图
图C 链表示意图

 

        当然,必须将第一个节点的地址 160 放到一个指针变量中,如H;最后一个节点没有后继,其指针域必须置空(即NULL),表明此表到此结束。这样就可以从第一个节点的地址开始“顺藤摸瓜”,找到表中的每个节点。
        作为线性表的一种存储结构,人们关心的是节点间的逻辑结构,而并不关心每个节点的实际地址,所以通常的单链表用如图C所示的形式表示而不用如图B 所示的形式表示,其中,符号“^”表示空指针(下同)。
        实际应用中通常用头指针来标识一个单链表,如单链表 L、单链表 H 等,是指某链表的第一 个节点的地址放在指针变量 L、H 中,头指针为“NULL”则表示一个空表。

        需要进一步指出的是: 上面定义的 LNode 是节点的类型,LinkList 是指向 LNode 类型节点的指针类型。为了增强程序的可读性,通常将标识一个链表的头指针定义为 LinkList 类型指针的变量,如LinkList L。当L有定义时,其值要么为 NULL(表示一个空表),要么为第一个节点的地址,即链表的头指针。将运算中用到指向某节点的指针变量说明为: LNode *类型,如 

LinkList *p;

        则语句“p=malloc(sizeof(LNode));”完成了申请一块 LNode 类型的存储单元的运算,并将其地址赋值给指针变量 p。如图D所示,指针变量 p 所指的节点为*p,*p 的类型为 LNode 型,所以该节点的数据域为(*p).data 或 p->data指针域为(*p).next 或 p->next,而语句“free(p);”则表示释放指针变量p所指的节点。 

图D 申请一个节点

三、单链表基本运算的实现: 

 💦建立单链表:

 ❤️在链表的头部插入节点建立单链表:

        链表与顺序表不同,它是一种动态管理的存储结构,链表中的每个节点占用的存储空间不是预先分配的,而是运行时系统根据需求生成的。因此,建立单链表要从空表开始,每读入一个数据元素则申请一个节点,然后插在链表的头部,图E展现了线性表(25,45,18,76,29)的链表建立过程,因为是在链表的头部插入,所以读入数据的顺序和线性表中的逻辑顺序是相反的

图E  在链表头部插入节点建立单链表
⭐单链表的建立算法(头部插入)。 
LinkList Creat_LinkList1(){
	LinkList L=NULL;//空表L为表头
	LNode *s;
	int x;			//设数据元素的类型为int型 
	scanf("%d",&x);
	while(x!=flag){//设flag为数据元素输入结束的标志 
		s=malloc(sizeof(LNode));//为插入数据元素申请空间 
		s->next=L;			//将插入数据元素置入申请到的单元中 
		L=s;
		scanf("%d",&x); 
	} 
	return L;
}  

 ❤️在单链表的尾部插入节点建立单链表:

        头部插入建立单链表虽然简单,但读入的数据元素的顺序与生成的链表中数据元素的顺序是相反的。若希望次序一致,则用尾部插入的方法。因为每次运算都是将新节点插入到链表的尾部,所以需加入一个指针 R 用来始终指向链表中的尾节点。图 F展现了在表尾部插入节点建立链表的过程。 

图F  在链表尾部插入节点建立单链表

 

         算法思路:初始状态时,头指针 H=NULL,尾指针 R=NULL,按线性表中数据元素的顺序依次读入数据元素,不是结束标志时,申请节点,将新节点插入到R 所指节点的后面,然后R指向新节点。

⭐单链表的建立算法(尾部插入)。
LinkList Creat_LinkList2(){
	LinkList *s,*R=NULL;
	int x;//设数据元素的类型为int型
	scanf("%d",&x);
	while(x!=flag){
		s=malloc(sizeof(LNode));s->data=x;//申请空间并将插入数据元素置入该单元 
		if(L==NULL){
			L=s;//第一个节点的处理 
		} 
		else{
			R->next=s;//其他节点的处理 
		} 
		R=s;//R重新指向新的尾节点 
		scanf("%d",&x); 
	} 
	if(R!=RULL){
		R->next=NULL;//对于非空表,将尾节点的next指针置空 
	} 
	return L; 
}

 ❤️在带头节点单链表的表尾插入数据元素建立单链表:

        在上面的算法中,第一个节点的处理和其他节点是不同的,原因是第一个节点加入时链表为空,它没有直接前趋节点,它的地址就是整个链表的指针,需要放在链表的头指针变量中;而其他节点有直接前趋节点,其地址放入直接前趋节点的指针域。第一个节点的问题在很多运算中都会遇到,如在链表中插入节点时,将节点插在第一个节点位置和其他节点位置是不同的,在链表中删除节点时,删除第一个节点和其他节点的处理也是不同的。
        为了方便运算,有时在链表的头部加入一个头节点,头节点的类型与数据节点一致,标识链表的头指针变量L中存放该节点的地址,这样即使是空表,头指针变量L也不为空了。头节点的加入使得第一个节点的问题不再存在,也使得空表和非空表的处理一致。
        头节点的加入完全是为了运算的方便,它的数据域无定义,指针域中存放的是第一个数据节点的地址,当空表时该指针域为空。

        图G 和图H 分别是带头节点的单链表空表和非空表的示意图。                           

 

图G  空表
图H  非空表

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java 线程同步和通信

Android 11 废弃了AsyncTask 线程 Thread: 通过start 开启 源码: start0 native方法 通过虚拟机跟操作系统交互 进程和线程区别: 进程是操作系统的独立区域,各个区域互不干扰,一个进程可以有多条线程同时工作,进程大于线程,线程依赖进程,线程间可以共享资源 Runnable: 接口…

利用 FormData 实现文件上传、监控网路速度和上传进度

利用 FormData 实现文件上传 基础功能:上传文件 演示如下: 概括流程: 前端:把文件数据获取并 append 到 FormData 对象中后端:通过 ctx.request.files 对象拿到二进制数据,获得 node 暂存的文件路径 前端…

用 LangChain 搭建基于 Notion 文档的 RAG 应用

如何通过语言模型查询 Notion 文档?LangChain 和 Milvus 缺一不可。 在整个过程中,我们会将 LangChain 作为框架,Milvus 作为相似性搜索引擎,用二者搭建一个基本的检索增强生成(RAG)应用。在之前的文章中&a…

华为电视盒子 EC6108V9C 刷机成linux系统

场景: 提示:这里简述项目相关背景: 家里装宽带的时候会自带电视盒子,但是由于某些原因电视盒子没有用,于是就只能摆在那里吃土,闲来无事,搞一下 问题描述 提示:这里描述项目中遇到…

[FC][常见Mapper IRQ研究]

本次IRQ研究了如下: VRC2&4(Mapper21,23,25) VRC3(Mapper73) VRC6(Mapper24 & Mapper26) VRC7(Mapper85) MMC3(Mapper4) MMC4(Mapper10) MMC5(Mapper5) Mapper18 Mapper64 Namco163(Mapper19) Sunsoft FME-7(Mapper69) 共计11种Mapper的IRQ操作使用例子 代码内有详细注…

【CANoe】CANoe工具使用-实现CAN通道的收、发、录、回放报文

目录 资源及目标 1. 配置工程 1.1 新建配置工程 1.2 配置两路CANoe虚拟通道 1.3配置CAN通道参数 1.3.1 配置CAN1类型(标准CAN或者CANFD),以及波特率(CANFD需要配置数据场和仲裁场两个段的波特率) 1.3.2配置CAN1…

电梯安全远程监控系统解决方案

一、方案背景 随着万丈高楼的平地起,电梯也成为了我们出入高层建筑最常用的工具之一。面对电梯数量的不断增加,电梯安全事故也是相继频发,因此关于电梯的安全运行就越来越受到社会各界的关注。电梯的使用在给人们出入高层建筑带来便利的同时&…

Normalizing Kalman Filters for Multivariate Time Series Analysis

l l l means latent state,LGM means ‘linear Gaussian state space models’ 辅助信息 作者未提供代码

高端网站设计公司 -蓝蓝设计数据可视化大屏服务

UI设计公司-蓝蓝设计(北京兰亭妙微科技有限公司)是一支由清华美院毕业的专业团队组成的设计公司。我们的设计师们在大屏科研信息软件UI设计领域拥有多年的工作经验和丰富的行业知识。我们对设计充满热爱,设计不仅是我们的专业和职业&#xff…

五、ZooKeeper的shell操作

目录 1、客户端连接 2、shell基本操作 2.1 操作命令

2023-12-02 LeetCode每日一题(拼车)

2023-12-02每日一题 一、题目编号 1094. 拼车二、题目链接 点击跳转到题目位置 三、题目描述 车上最初有 capacity 个空座位。车 只能 向一个方向行驶(也就是说,不允许掉头或改变方向) 给定整数 capacity 和一个数组 trips , trip[i] …

【SpringBoot3+Vue3】七【后续2】【番外篇】- (使用docke部署)

目录 一、maven打包后端服务 1、clean 2、package 3、查看jar包 二、部署java后端服务 1、使用dockerfile构建一个java17的镜像 1.1 使用dokcerfile构建容器命令 1.2 方式一 将jar打包进容器镜像 1.3 方式二 jar不打包进容器镜像,通过映射主机目录映射方式…

【数字图像处理】边缘检测

边缘检测是一种图像处理技术,用于在图像中识别和提取物体边缘的信息,广泛应用于计算机视觉和图像分析领域。本文主要介绍数字图像边缘检测的基本原理,并记录在紫光同创 PGL22G FPGA 平台的布署与实现过程。 目录 1 边缘检测原理 2 FPGA 布署…

持续集成交付CICD:GitLabCI 运行前后端项目

目录 一、理论 1.spring项目自动构建 2.阿里云云效 Maven 3.Maven安装 4.Go安装 5.NPM安装 二、实验 1.GitLabCI 运行Maven项目 2.GitLabCI 运行Go项目 3.GitLabCI 运行NPM项目 三、问题 1.前端脚手架如何初始化项目 2.NPM下载如何指定 3.Go项目下载源如何指定 …

基于DigiThread的仿真模型调参功能

仿真模型调参是指通过调整模型内部的参数值,使仿真模型的输出更符合实际系统的行为或者预期结果的过程。 仿真过程中,往往需要频繁对模型参数进行调整,通过观察不同参数下系统整体的运行情况,实现系统的性能、可靠性和效率的优化…

UDP通信

UDP通信-快速入门 客户端程序 服务端程序 步骤 UDP通信-多发多收 客户端 服务端 步骤

Sentinel核心类解读:Node

基本介绍 Sentinel中的簇点链路是由一个个的Node组成的,Node是一个接口。Node中保存了对资源的实时数据的统计,Sentinel中的限流或者降级等功能就是通过Node中的数据进行判断的。 Sentinel中是这样描述Node的: Holds real-time statistics…

抑郁症中西医治疗对比?

抑郁症是一种常见的心理障碍,治疗方法包括中医和西医两种。下面就抑郁症中西医治疗进行对比: 治疗方法:中医治疗抑郁症强调整体观念和辨证论治,通过调理身体各部分的功能,达到治疗抑郁症的目的。中医治疗抑郁症多采用天…

YOLOv8创新魔改教程(一)如何进行模块创新

YOLOv8创新魔改教程(一)如何进行模块创新 YOLOv8创新魔改教程 本人研一,最近好多朋友问我要如何修改模型创新模块,就想着不如直接开个专栏歇一歇文章,也算是对自己学习的总结,本专栏以YOLOv8为例&#xf…

FH Admin Shiro反序列化漏洞复现

0x01 产品简介 FH Admin 是一款 java 快速开发平台。 0x02 漏洞概述 FH Admin CMS 存在 shiro 反序列化漏洞,该漏洞源于软件存在硬编码的 shiro-key,攻击者可利用该 key 生成恶意的序列化数据,在服务器上执行任意代码,执行系统命…