【奇妙的数据结构世界】用图像和代码对链表的使用进行透彻学习 | C++

news2024/11/28 19:38:39

第九章    链表


目录

第九章    链表

●前言

●一、链表是什么?

1.简要介绍

2.具体情况

●二、链表操作的关键代码段

1.类型定义

2.常用操作

●总结


前言

        简单来说,数据结构是一种辅助程序设计并且进行优化的方法论,它不仅讨论数据的存储与处理的方法,同时也考虑到了数据彼此之间的关系与运算,从而极大程度的提高程序执行的效率,减少对内存空间的占用等。不同种类的数据结构适用于不同的程序应用,选择合适正确的数据结构,可以让算法发挥出更大的性能,给设计的程序带来更高效率的算法。


一、链表是什么?

1.简要介绍

        链表也被称为动态数据结构,它使用不连续的内存空间来存储数据元素,由许多相同数据类型的数据项按特定顺序排列而成的线性表。链表中的各个数据在计算机的内存中是不连续且随机存放的,所以对它进行插入和删除操作不需要移动大量的数据,因此是相当方便的。如果要有新的元素加入链表,那么就需要向系统去申请内存空间。如果数据被删除后,就把这块内存空间释放还给系统。但是在代码中对其数据结构进行设计时较为麻烦,以及查询数据元素时不能像静态数据结构那样按索引值去直接进行访问,而是需要从前到后依次遍历查找,直到找到该数据元素为止。

2.具体情况

        在日常生活中,链表有许多抽象概念的运用。例如以前的火车,当乘坐的人多时就添加一些车厢;而当人少时就减少一些车厢;这就很像一个典型的单向链表的抽象运用。生活中还有很多链表这类抽象概念的运用。

图片来源于网络

         在动态分配内存空间的时候,单向链表是我们经常使用到的。每个单向链表由多个结点组成的,每个结点又是由数据域和指针域组成的。数据域中存储数据,指针域中放着指向下一个元素在内存中的地址。在单向链表中第一个结点是链表的头结点,并且头指针指向头结点。最后一个结点是该链表的尾结点。具体情况如下图所示:

单链表示意图

         因为在单链表中,所有结点都知道自己下一个结点在哪个位置。但前一个的结点信息确无法得知,所以头指针L在链表的各项操作中就显得非常重要。只要链表中头指针存在就可以访问遍历整个链表的具体情况,并且进行一系列相关的操作。单链表是我们在数据结构中比较常用的,用它就可以去解决绝大部分的链表类程序设计的题型。但是链表中除了单链表,还有双向链表和循环链表这两类相对于单向链表是不常用的两种链表数据结构。具体如下图所示:

双向链表和循环链表示意图

二、链表操作的关键代码段

1.类型定义

①单链表存储结构的定义(重点)

typedef struct lnode{
	elemtype data;   //数据域
	struct lnode *next;  //指针域
}lnode,*linklist;   
//lnode *p 结点指针定义
//linklist &L  单链表L定义

 ②双向链表存储结构的定义

typedef struct lnode {
	elemtype data;   数据域
	struct lnode* prior, * next;  前后指针域
}lnode,*linklist;
//lnode *p 结点指针定义
//linklist &L  单链表L定义

③循环链表存储结构的定义

(将单链表的头尾用指针进行相连)

typedef struct lnode {
	elemtype data;
	struct lnode* next;
}lnode,*linklist;
linklist connect(linklist ta,linklist tb)  //ta为头 tb为尾
{
	lnode* p;
	p = ta->next;   //将头结点的指针域保存
	ta->next=tb->next->next;  //将尾结点指针域的下一个区域连接到头结点的指针域
	delete tb->next;  //将尾结点的指针域删除,因为他将连接到头结点那里
	tb->next = p;   //将头结点的指针再次绑定到已经循环回来的tb上
	return tb;
}

2.常用操作

①链表初始化

初始化的链表为空链表
void initlist(linklist& L)
{
	L = new lnode;   //创建一块新的结点区域
	L->next = NULL;   //将这个结点区域的指针域赋为空
}

 ②判断链表是否为空

bool listempty(linklist& L)
{ 
	//常规判断
	if (L->next)
		return true;
	else
		return false;
}

③ 链表的清空

 

void clearlist(linklist& L)
{
	lnode* p;
	lnode* q; //定义两个结点指针
	p=L->next;  //将链表头结点的指针域指向的下个结点赋给指针p
	while (p)  //如果指针p存在,则开始循环判断
	{
		q = p->next;   //循环中事先将p的再下一个指针域指向的元素赋给指针q
		delete p;   //删除此时的指针p,此时p将无内容
		p = q;   //再将q中的内容赋给p,进行继续的循环判断即可
	}
	L->next = NULL;    //将链表修改成了初始化下的状态
}

 ④链表的销毁

void destorylist(linklist& L)
{
	lnode* p;
	L=L->next;
	while (L != NULL)  //循环判断,直到链表的结点被删除为空为止
	{
		p = L;   
		L = L->next;
		delete p;   //删除结点
	}
}

⑤ 链表的表长

int lengthlist(linklist& L)
{
	lnode* p;
	p=L->next;
	int i = 0;  //将用来展示链表的长度
	while (p)  //如果结点存在,从前到后遍历循环判断
	{
		i++;  //进行计数
		p = p->next;   //指针继续向后指向链表后面的指针域,用于循环的下一次判断
	}
	return 1;
}

⑥取链表中的第i个数据域的内容

int getelem(linklist& L,int i,elemtype e)
{
	lnode* p;
	p = L->next;
	int j = 1;
	//要取第i个元素的内容,首先进行循环判断,让指针p从前向后移动,移动i次
	while (p && j < i)   //两个条件:p存在,计数的j小于i
	{
		p = p->next;
		j++;
	}
	//进行一个判断,判断循环完的p是否存在,j是否满足条件
	if (!p || j > i) {
		return 0;
	}
	else {
		e = p->data;
		return 1;
	}
}

 ⑦在第i个结点前插入值为e的新结点

int insertlist(linklist& L,int i,elemtype e)
{
	lnode* p;
	p = L->next;
	int j = 0;
	while (p&&j<i-1)
	{
		p = p->next;
		j++;
	}
	if (!p || j > i - 1) {
		return 0;
	}
	else {
		linklist s;//因为需要重新添加一个结点信息,所以需要new一块新的结点区域
		s = new lnode;
		s->data = e;   //将数据元素插入该结点的数据域
		s->next=p->next;  //将最初p结点的下一个结点的地址赋给新的结点s的指针域
		p->next = s;//直接将s的地址,赋给p的指针域
		return 1;
	} 
}

⑧  删除第i个结点

int deletelist(linklist& L, int i, elemtype e)
{
	lnode* p;
	lnode* q;
	p = L->next;
	int j = 0;
	while (p && j< i - 1)
	{
		p = p->next;
		j++;
	}
	if (!p || j > i - 1) {
		return 0;
	}
	else {
		q = p->next;   //此时结点p的下一个结点就是要去删除的结点,将这个位置赋给指针q
		p->next=q->next;//将要删除的前后结点连起来,不去影响该链表
		e=q->data;  //用e先将要删除结点中的数据元素保存下来
		delete q;  //删除要删除的结点
		return 1;
	}
}

⑨头插法(前提是已经通过初始化创建了一个空链表)

void insertlist_head(linklist& L,int n)
{
	linklist head_s;
	for (int i = n; i > 0; i--)
	{
		head_s = new lnode;     //创建新的结点
		cin >> head_s->data;   //输入数据域的数据
		head_s->next=L->next;  //进行结点间的连接
		L->next = head_s;   //进行结点间的连接
	}
}

⑩尾插法(前提是已经通过初始化创建了一个空链表)

void insertlist_tail(linklist& L, int n)
{
	linklist tail_s;
	lnode* p;
	p = L;
	for (int i = 1; i <= n; i++)
	{
		tail_s = new lnode;
		cin >> tail_s->data;
		tail_s->next = NULL;  //每次都将新创建结点的指针域置为空
		p->next = tail_s;
		p = tail_s;
	}
}

总结

        以上就是我们对链表关键操作代码段的讲解。如果你可以完全掌握上面的代码段,那么你就可以利用这些数据结构算法来解决关于链表这一类的相关问题了,并且如果你能够在一些其他类的程序设计问题中巧用链表,那么你就可以更快、更好、更方便的去解决你所要去解决的问题。

                                               <您的三连和关注是我最大的动力>

                       🚀 文章作者:Keanu Zhang        分类专栏:算法之美(C++系列文章)

 

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

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

相关文章

打工人必知必会(一)——规章制度保险劳动合同变更

目录 参考 1、规章制度的生效要件 2、工资的发放形式 3、社会保险的基本规定 4、基本养老保险 5、医疗保险、失业保险、工伤保险、生育保险 6、劳动合同的变更 第一节 协商变更劳动合同 第二节 单方变更劳动合同 参考 《HR全程法律顾问&#xff1a;企业人力资源管理高…

5-6中央处理器-多处理器系统硬件多线程

文章目录一.多处理器系统&#xff08;一&#xff09;计算机体系结构分类1.单指令单数据流SISD2.单指令多数据流SIMD3.多指令单数据流MISD4.多指令多数据流MIMD&#xff08;1&#xff09;(共享内存)多处理器系统/多核处理器&#xff08;2&#xff09;多计算机系统&#xff08;二…

逆水寒魔兽老兵服副本攻略及代码分析(英雄武林风云录,后续更新舞阳城、扬州、清明等副本攻略)

文章目录一、武林风云录1&#xff09;老一&#xff1a;陈斩槐&#xff08;只有四个机制&#xff0c;dps压力不大&#xff0c;留爆发打影子就行&#xff09;&#xff08;1&#xff09;点名红色扇形区域&#xff08;2&#xff09;点名红色长条&#xff0c;注意最后还有一段大劈&a…

MongoDB入门(特点,使用场景,命令行操作,SpringData-MongoDB)

今天我们将通过这一篇博客来了解MongoDB的体系结构&#xff0c;命令行操作和在JAVA 当中使用SpringData-MongoDB 来 操作MongoDB。 如果没有安装的小伙伴 可以看一下 这篇文章 (59条消息) 开源的文档型数据库–MongoDB&#xff08;安装&#xff09;_一切总会归于平淡的博客-CS…

LeetCode[128]最长连续序列

难度&#xff1a;中等题目&#xff1a;给定一个未排序的整数数组 nums&#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。请你设计并实现时间复杂度为 O(n)的算法解决此问题。示例 1&#xff1a;输入&#xff1a;nums [100,4,2…

java中new的含义如何理解?

在Java中&#xff0c;new关键字被使用来创建一个新的对象&#xff0c;可以理解为创建的意思。使用关键字new来创建一个对象也叫类的实例化&#xff0c;使用new创建对象时&#xff0c;会调用构造方法初始化对象声明对象Cat cat 在栈内存中实例化对象 new Cat(参数); 在堆内存中每…

C++:类的static成员,友元和构造函数初始化列表

目录 一.类的构造函数的初始化列表 1.类的构造函数初始化列表的引入和介绍 2.初始化列表用于类的类对象成员的拷贝构造函数的调用 3.初始化列表的使用细则 4.使用初始化列表的一个注意事项 二.explicit关键字 三.C类的static成员 1.类中static修饰的成员变量 2.类中st…

Lesson 4.2 逻辑回归参数估计:极大似然估计、相对熵与交叉熵损失函数

文章目录一、逻辑回归参数估计基本思路1. 构建损失函数2. 损失函数求解二、利用极大似然估计进行参数估计三、熵、相对熵与交叉熵1. 熵&#xff08;entropy&#xff09;的基本概念与计算公式2. 熵的基本性质3. 相对熵&#xff08;relative entropy&#xff09;与交叉熵&#xf…

LeetCode[947]移除最多的同行或同列石头

难度&#xff1a;中等题目&#xff1a;n块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。如果一块石头的 同行或者同列 上有其他石头存在&#xff0c;那么就可以移除这块石头。给你一个长度为 n的数组 stones&#xff0c;其中 stones[i] [xi, yi]…

MATLAB算法实战应用案例精讲-【人工智能】Grover量子搜索算法(补充篇)

前言 因为量子计算的并行性, 搜索问题, 比如说数据库搜索, 最短路径问题, 加密问题, 图形着色问题等, 都被视为可以做到量子加速. Grover 算法,有时也称为量子搜索算法(quantum search algorithm),指一种在量子计算机上运行的非结构化搜索算法,是量子计算的典型算法…

LeetCode[765]情侣牵手

难度&#xff1a;困难题目&#xff1a;n对情侣坐在连续排列的 2n个座位上&#xff0c;想要牵到对方的手。人和座位由一个整数数组 row表示&#xff0c;其中 row[i]是坐在第 i 个座位上的人的 ID。情侣们按顺序编号&#xff0c;第一对是 (0, 1)&#xff0c;第二对是 (2, 3)&…

#A. Balanced Lineup排队(rmq模板题)

题目思路建议先看看详解rmq问题很明显这道题意是跟你一段数列&#xff0c;并给出多次询问,询问区间内最大值和最小值的差。如果去暴力枚举显然会超时,所以要用st算法来解决。我们要建立两个RMQ预处理内容&#xff0c;分别处理最大值和最小值。建一个mx[i][j]代表从i开始,长度为…

精品图表Crack:TeeChart ActiveX version 2023.1

TeeChart ActiveX version 2023 数据可视化专家,Visual Studio.Net、Visual Basic、Visual Studio 6和 IIS / ASP的图表组件 概述 TeeChart Pro ActiveX 图表组件库提供数百种 2D 和 3D 图形样式、56 种数学和统计函数供您选择&#xff0c;以及无限数量的轴和 14 个工具箱组件…

DFS(五)最小轮盘锁

752. 打开转盘锁 你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字&#xff1a; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 。每个拨轮可以自由旋转&#xff1a;例如把 9 变为 0&#xff0c;0 变为 9 。每次旋转都只能旋转一个拨轮的一位数字。 锁的初始数字为 0000 &#xff0c;一…

【2023.01.26】定时执行专家 V6.6 兔年春节版 - 更新日志

目录 ◆ 最新版下载链接 ◆ 软件更新日志 – TimingExecutor Full Change Log ▼ 2023-01-23 V6.6 ▼ 2023-01-20 V6.5 ▼ 2022-12-25 V6.4 ▼ 2022-11-15 V6.3 ▼ 2022-10-01 V6.2 ▼ 2022-07-30 V6.1&#xff08;Build 769.30072022&#xff09; ▼ 2022-0…

Linux-Ubuntu入门到精通之远程操作指令

1️⃣shutdown 2️⃣查看或配置网卡信息 3️⃣网卡和IP地址 4️⃣ifconfig 5️⃣ping 6️⃣远程登录和复制文件 7️⃣ ssh 基础&#xff08;重点&#xff09; 8️⃣域名 和 端口号 9️⃣SSH 客户端的简单使用 1️⃣0️⃣Windows 下 SSH 客户端的安装 Putty &#xff1a;http:/…

数据结构 | 海量数据处理 | 位图和哈希切分的常见应用 | 布隆过滤器的使用场景

文章目录位图应用question 1question 2question 3位图的作用哈希切分布隆过滤器作为一种数据结构&#xff0c;哈希桶有着不同于其他数据结构的思想——直接映射&#xff0c;这使得在哈希结构中查找数据的效率达到了最快的O(1)&#xff0c;比起搜索树的比较数据大小&#xff0c;…

数学建模——降维算法

降维 降维的意义 降低无效、错误数据对建模的影响&#xff0c;提高建模的准确性少量切具有代表性的数据将大幅缩减挖掘所需的时间降低存储数据的成本 需要降维的情况 维度灾难。很难有一个简洁的模型在高维空间中依旧具有鲁棒性&#xff0c;而随着模型复杂度的增加&#xf…

【LeetCode每日一题:1663. 具有给定数值的最小字符串~~~递归+DFS+贪心】

题目描述 小写字符 的 数值 是它在字母表中的位置&#xff08;从 1 开始&#xff09;&#xff0c;因此 a 的数值为 1 &#xff0c;b 的数值为 2 &#xff0c;c 的数值为 3 &#xff0c;以此类推。 字符串由若干小写字符组成&#xff0c;字符串的数值 为各字符的数值之和。例如…

你会仲裁吗——劳动仲裁需要准备

目录 劳动仲裁申请书 仲裁思路 ​编辑 一、仲裁前准备 1、自己不认可年终奖 2、自己不认可绩效 二、【仲裁前】协商阶段 1、主张3个月足额年终奖 2、公司协商离职赔偿方案 年终奖仲裁证据 延时加班费 周末加班费 节假日加班费 其他福利-如房补 申请劳动仲裁交通…