数据结构与算法之美笔记——链表(上)

2024-06-09 09:48

本文主要是介绍数据结构与算法之美笔记——链表(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘要:

链表和数组一样,也是基础常用的数据结构之一,由于采取了与数组不同的数据存储方式,导致链表的随机访问、插入和删除操作时间复杂度都为 O ( n ) O(n) O(n),链表有多种类型,如单链表、循环链表和双向链表等。

链表的特性

链表有许多类型,接下来先以最简单的单链表进行分析。要了解链表的特性先得了解链表是如何存储的,链表每个存储单元被称为「结点」,结点不仅会存储数据本身,还会存储一个指向下一结点的指针,这个指针称为「后继指针」,链表的第一个结点被叫做「头结点」,最后一个结点被称为「尾结点」,链表可以依靠头结点查找整个链,而尾结点后继指针通常不指向其他结点,所以尾结点的后继指针存储空地址。

链表与数组存储方式的区别说明了链表不需要进行连续存储空间的申请,这样对存储的利用率比较高,不会像数组因为申请不到相应大小的连续存储空间导致失败。

随机访问、插入、删除的时间复杂度

根据链表的特点,如果需要随机访问链表中的某个结点,链表只能从头结点开始依靠后继指针遍历结点,直到查找到相应结点结束,假设链表结点个数为 n,随机访问每个结点的机率相同,都为 1 / n 1/n 1/n,访问每个结点时分别需要遍历链表结点 1,2,3,...,n 次,所以时间复杂度为

T ( n ) = 1 n + 2 n + 3 n + . . . + n n = n × ( n + 1 ) 2 n = n + 1 2 = O ( n ) T(n)=\frac{1}{n}+\frac{2}{n}+\frac{3}{n}+...+\frac{n}{n}=\frac{\frac{n\times(n+1)}{2}}{n}=\frac{n+1}{2}=O(n) T(n)=n1+n2+n3+...+nn=n2n×(n+1)=2n+1=O(n)

进行插入操作时,只需要在结点要插入的地方将前一个结点指向需要插入的结点,插入的结点再指向下一个结点即可,所以时间复杂度为 O ( 1 ) O(1) O(1),删除操作也是同理,将需要删除结点的前一结点指向删除结点的后一结点即可,时间复杂度也是 O ( 1 ) O(1) O(1),插入和删除操作可对照下图进行理解。

链表插入删除操作图

可以将以上链表的分析与数组类似操作对比,能够看出链表结点因为不是使用连续存储空间存储,所以随机访问时间复杂度比较高,但同样也是因为不需要像数组一样保持连续存储空间,在插入和删除操作时不需要和数组一样进行数据搬移,所以时间复杂度比较低。

链表类型

链表主要有「单链表」、「循环链表」和「双向链表」三种类型,单链表在上面的例子中已经详细讲过,接下来分析复杂一些的循环链表和双向链表。

循环链表

循环链表就是指链表的尾结点后继指针是指向头结点的链表,这样的链表从尾结点到头结点会比较方便,适合处理环型结构的数据。

循环链表

双向链表

双向链表指链表中的结点在指向后面一个结点的同时也会指向前面一个结点,有两个方向,结点中指向前一个结点的指针叫做「前驱指针」。双向链表因为支持链表两个方向的遍历,所以在进行插入和删除操作时比单链表更加高效。

双向链表

双向链表的插入和删除

之前分析过单链表的插入和删除时间复杂度都是 O ( 1 ) O(1) O(1),双向链表比单链表的插入、删除操作更加高效的话还能将时间复杂度降低到什么程度?

其实单链表分析的插入和删除操作的时间复杂度并不全面,下面以删除结点为例分析,在实际中对链表的删除操作存在两种情况

  • 删除指定值的结点
  • 删除指定指针的结点

如果是删除指定值的结点,无论是单链表还是双向链表都需要遍历结点进行删除,虽然删除操作时间复杂度是 O ( 1 ) O(1) O(1),但是查找结点时间复杂度是 O ( n ) O(n) O(n),根据时间复杂度的加法法则,整个删除操作时间复杂度是 O ( n ) O(n) O(n)

如果是删除指定指针的结点的情况,通过指定指针就可以找到需要删除的结点,但删除操作需要先找到当前结点的前一个结点,单链表就需要对链表进行遍历找到前一个结点,时间复杂度就为 O ( n ) O(n) O(n),而双向链表因为存储有前驱指针,可以在 O ( 1 ) O(1) O(1) 时间复杂度下找到前一个结点,所以这种情况下的删除操作双向链表可以将时间复杂降为 O ( 1 ) O(1) O(1),插入结点同理。

虽然双向链表在操作上更加方便高效,但是双向链表的结点需要使用更多的空间来存储前驱指针,在结点存储的数据占存储较小的情况下存储指针的资源消耗比较明显,当结点存储的数据占据存储比较大时,存储前驱指针消耗也就可以忽略,这也是算法中「空间换时间」的思想。

课后题目

判断回文链表
题目解答可点击此处查看。


文章中如有问题欢迎留言指正
数据结构与算法之美笔记系列将会做为我对王争老师此专栏的学习笔记,如想了解更多王争老师专栏的详情请到极客时间自行搜索。

这篇关于数据结构与算法之美笔记——链表(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1044836

相关文章

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

《offer来了》第二章学习笔记

1.集合 Java四种集合:List、Queue、Set和Map 1.1.List:可重复 有序的Collection ArrayList: 基于数组实现,增删慢,查询快,线程不安全 Vector: 基于数组实现,增删慢,查询快,线程安全 LinkedList: 基于双向链实现,增删快,查询慢,线程不安全 1.2.Queue:队列 ArrayBlockingQueue:

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

操作系统实训复习笔记(1)

目录 Linux vi/vim编辑器(简单) (1)vi/vim基本用法。 (2)vi/vim基础操作。 进程基础操作(简单) (1)fork()函数。 写文件系统函数(中等) ​编辑 (1)C语言读取文件。 (2)C语言写入文件。 1、write()函数。  读文件系统函数(简单) (1)read()函数。 作者本人的操作系统实训复习笔记 Linux

【数据结构】线性表:顺序表

文章目录 1. 线性表2. 顺序表2.1 概念及结构2.2 接口实现2.3 顺序表的问题及思考 1. 线性表 线性表是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串… 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式

LVGL快速入门笔记

目录 一、基础知识 1. 基础对象(lv_obj) 2. 基础对象的大小(size) 3. 基础对象的位置(position) 3.1 直接设置方式 3.2 参照父对象对齐 3.3 获取位置 4. 基础对象的盒子模型(border-box) 5. 基础对象的样式(styles) 5.1 样式的状态和部分 5.1.1 对象可以处于以下状态States的组合: 5.1.2 对象

DDS信号的发生器(验证篇)——FPGA学习笔记8

前言:第一部分详细讲解DDS核心框图,还请读者深入阅读第一部分,以便理解DDS核心思想 三刷小梅哥视频总结! 小梅哥https://www.corecourse.com/lander 一、DDS简介         DDS(Direct Digital Synthesizer)即数字合成器,是一种新型的频率合成技术,具有低成本、低功耗、高分辨率、频率转换时间短、相位连续性好等优点,对数字信

数据结构9——排序

一、冒泡排序 冒泡排序(Bubble Sort),顾名思义,就是指越小的元素会经由交换慢慢“浮”到数列的顶端。 算法原理 从左到右,依次比较相邻的元素大小,更大的元素交换到右边;从第一组相邻元素比较到最后一组相邻元素,这一步结束最后一个元素必然是参与比较的元素中最大的元素;按照大的居右原则,重新从左到后比较,前一轮中得到的最后一个元素不参4与比较,得出新一轮的最大元素;按照上述规则,每一轮结