【追求卓越02】数据结构--链表

引导

        今天我们进入链表的学习,我相信大家对链表都很熟悉。链表和数组一样,作为最基础的数据结构。在我们的工作中常常会使用到。但是我们真的了解到数组和链表的区别吗?什么时候使用数组,什么时候使用链表,能够正确的选取吗?

        链表需要我们进行一些练习才能更好的掌握。我后面也会结合几个经典的练习题进行训练。

链表和数组区别

        数组和链表的最大区别就是存储了。从上一栏,我们了解到数组的存储结构是连续的。链表与之恰恰相反,它可以利用内存中零碎的内存空间。如图:

        这样就存在一个问题;当我们向内存申请100M的数组时,即使内存剩余200M内存,但经常会提示申请失败“out of memory”。因为内存中存在着很多的内存碎片,导致200M内存中基本不存在100M连续的。但是链表就不会存在这种情况,因为它支持动态分配,不需要内存地址上的连续要求。

单链表

        单链表,是比较简单的了,并且也比较常见。结构图如下:

单链表的删除,新增操作的时间复杂度

        我们知道数组的删除,新增操作,要进行数据的搬移(保证数据的连续性)。导致数组的复杂度为O(n)。但是单链表并不需要进行数据的搬移,只要修改节点的指针的指向即可。所以链表的复杂度时O(1)

单链表的随机访问的时间复杂度

        数组的存储是连续的,当知道下标时,数组复杂度O(1);但是链表由于不是连续存储的,所以在访问第i个节点时,需要从头节点,一个接一个遍历。因此链表复杂度O(n)

循环链表

        循环链表其实就是特殊的单链表(尾节点指向了头节点)。因此它也不是很难。不过对于特殊的问题,使用循环链表比较方便。比图经典的约瑟夫问题。结构图如下:

双向链表

        双向链表虽然我们接触的不多,但在项目中,双向链表比单链表使用的更加广泛。 双向链表其实就是多了一个指针变量,指向了前节点。结构图如下:

        正如我们上面说的双向链表在工作中使用的往往比单链表要广泛,为什么呢

从链表的删除举例,删除链表的中节点,无非就是以下两种情况:

  1. 删除节点中,值等于某个特定值的节点
  2. 删除给定指针指向的节点

        对于第一种情况,无论是单链表或双链表都要先找到对应的节点,再进行删除操作。 根据复杂度的加法原则,O(n)+O(1)=O(n)。两者的复杂度都是O(n)。

        对于第二种情况,给定一个需要删除节点之后,仅需要将该节点的前节点指向该节点的下一个节点即可。

        但是单向链表需要进行遍历,找到该节点的前节点。需要O(n)。所以单链表需要O(n)。但是由于双向链表每个节点有指向前节点的指针。故双向链表仅需O(1)。

        其实第二种情况,是我们经常会遇到的,比如LinkedHashMap容器,就是使用了双向链表。

        不仅仅时删除和插入操作,双向链表比单向链表高效。其实查询也会比单向链表高效。比如在一个有序的链表中,我们可以保存上一次查询节点,判断查询值的大小,采取向上还是从下查询的方式。

        其实这就是一个空间换时间的例子,双向链表虽然比单向链表要高效,但是它比单向链表多一个指针变量。因此消耗的内存资源也会比较多。

数组和链表的选择

我觉得数组和链表的选择应该要结合以下几点因素考虑:

1. 时间复杂度

        数组的随机访问时间复杂度是O(1),删除操作的复杂度O(n);链表的随机访问的复杂度是O(n),删除操作的复杂度O(1);结合你的业务逻辑,评价主要是查询操作居多还是删除操作居多。

2. 内存要求

        因为链表中每个节点需要一个指向下一个节点的指针变量,所以链表比数组消耗更多的内存资源。当你的内存资源比较有限的情况下,我还是建议你使用数组。

3. 性能提高--CPU缓存机制

        我们知道数组的访问比链表要高效。但是这只是从时间复杂度来分析的。但是不仅仅如此,数组在访问操作时,因为cache机制的存在,效率会更加高。因此,如果你想更进一步提高访问的效率,我建议你也选择数组。

总结:综上所述,数组有这么多的优势,我们是不是基本都选择数组呢?我们工作中基本还是选择链表较多。因为我们基本不会存在性能和内存资源上的担忧,并且链表使用起来还是比较方便的

什么是CPU缓存机制?

        上面我们谈到了CPU缓存机制,数组对CPU缓存机制比较友好能够加快访问效率,但是链表对其不友好,不能提高效率。但是何为CPU缓存机制呢?其实它是依据操作系统中局部性原理来实现的。

        所谓的局部性原理,包括两个部分:时间局部性空间局部性。时间局部性指的是最近访问的存储位置,很可能在不久的将来还要访问;空间局部性指存储访问有聚集的倾向,当访问了某一个位置之后,很有可能也要访问附近的位置。

        我们知道Cache是高速访问的缓存,比内存的访问还要快。CPU从内存中访问数据并不会仅仅只获取该地址的内容。而是会将该内容在内的物理块一起放到Cache缓存中。下次再读取内容时,首先再Cahce中找,找不到再从内存中重复上面的操作。

        因为数组的存储空间是连续的,所以能够很好的适应CPU缓存机制。但是链表是非连续存储的,所以对CPU缓存机制不友好。

总结

        了解了数组和链表之间的区别,以及如何选择数组和链表数据结构。数组对CPU缓存机制更加友好。

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

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

相关文章

笔记本外接显示器的一些基本操作

1>,安装问题直接问客服,正常情况是将显示屏接上电源,然后用先将显示屏和笔记本的HDMI接口连接即可。 按下组合键 win p ,选择 “复制”。 2>,接上显示屏后,原笔记本无声音? 1、找到笔记本电脑右下…

通过Everything 建立HTTP服务器时指定文件夹共享

在局域网传输文件,高效传输,不限文件大小 1、安装Everything 2、在Everything开启HTTP服务 【工具】—>>【选项】—>>【HTTP服务】启用HTTP服务器,设置HTTP服务器用户名和密码 3、查看网络信息 打开服务端电脑的【命令提示…

低权限(无权限)时如何在mysql客户端控制台的大量输出中快速定位mysql死锁或慢sql

查看mysql的查看死锁的方式很多,但很多时候我们普通开发者的权限比较低,无法执行某命令。比如本次就准备使用 SHOW ENGINE INNODB STATUS;命令,但客户端提示权限不够。后来本人找到了另一条低权限的命令 show full PROCESSLIST;但是show fu…

CST同轴馈电步骤

CST同轴馈电步骤 算例1. 同轴内芯2. 填充材料3. 外皮4. GND减去一个圆形,使EMWAVE可以通过5. 添加端口6. 结果比较 算例 cst模型库中的一个圆贴片 1. 同轴内芯 2. 填充材料 他这里直接使用和介质基板一样的材料并且进行了合并,我就懒得再改了&#x…

Matplotlib颜色条的配置_Python数据分析与可视化

Matplotlib颜色条配置 基本颜色颜色条选择配色方案颜色条刻度的限制与扩展功能的设置离散型颜色条 基本颜色 Matplotlib提供了8种指定颜色的方法: 在[0,1]中的浮点值的RGB或RGBA元组(例如 (0.1, 0.2, 0.5) 或(0.1, 0.…

3D电路板在线渲染案例

从概念上讲,这是有道理的,因为PCB印制电路板上的走线从一个连接到下一个连接的路线基本上是平面的。 然而,我们生活在一个 3 维世界中,能够以这种方式可视化电路以及相应的组件,对于设计过程很有帮助。本文将介绍KiCad中基本的3D查看功能,以及如何使用NSDT 3DConvert在线…

PHP中间件实现

目录 1、简单中间实现 2、使用闭包函数实现中间件 在PHP中,中间件是一种常用的设计模式,用于处理请求和响应,它可以在请求到达目标处理程序之前或响应发送给客户端之前执行一些特定的逻辑。中间件提供了一种灵活的方式来修改或扩展应用程序的…

数据库数据恢复—MongoDB数据库文件拷贝出现错误的数据恢复案例

MongoDB数据库数据恢复环境: 一台Windows Server操作系统的虚拟机,虚拟机上部署有MongoDB数据库。 MongoDB数据库故障&检测: 在未关闭MongoDB服务的情况下,工作人员将MongoDB数据库文件拷贝到其他分区,然后将原数…

Dubbo从入门到上天系列第十八篇:Dubbo引入Zookeeper等注册中心简介以及DubboAdmin简要介绍,为后续详解Dubbo各种注册中心做铺垫!

文章目录 一:Dubbo注册中心引言 1:什么是Dubbo的注册中心? 2:注册中心关系图解 3:引入注册中心服务执行流程 4:Dubbo注册中心好处 5:注册中心核心作用 二:注册中心实现方案 …

bclinux aarch64 ceph 14.2.10 云主机 性能对比FastCFS vdbench

部署参考 ceph-deploy bclinux aarch64 ceph 14.2.10-CSDN博客 ceph-deploy bclinux aarch64 ceph 14.2.10【3】vdbench fsd 文件系统测试-CSDN博客 ceph 14.2.10 aarch64 非集群内 客户端 挂载块设备-CSDN博客 FastCFS vdbench数据参考 bclinux aarch64 openeuler 20.03 …

每日一题:LeetCode-589.N叉树的前序遍历序列构造二叉树

每日一题系列(day 01) 前言: 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 🌈 &#x1f50e…

汇编-PROTO声明过程

64位汇编 64 模式中,PROTO 伪指令指定程序的外部过程,示例如下: ExitProcess PROTO ;指定外部过程,不需要参数.code main PROCmov ebx, 0FFFFFFFFh mov ecx,0 ;结束程序call ExitProcess ;调用外部过程main ENDP END 32位…

IO口电压下降那么多是怎么回事??

前几天一个工程师向我反馈他测得如下电路MCU IO口的电压不是3.3V,只有2V多。 IO配置的是输入功能,无上下拉。最初我不太相信这个结果,后来自己用万用表实际测量了下,还真是这个结果 这是咋回事呢?不应该电压就是3.3V吗…

智能小车速通版——手把手教程

考虑到大部分学校,会发放简易小车来作为智能车初期培训和筛选的工具, 于是,我写一个简单的教程,能够实现简单小车的电磁循迹。 通过这个教程,能够通过简化的步骤搭建寻迹小车,进而了解整个智能车是如何实…

Linux网络——传输层

目录 一.再谈端口概念 二.UDP协议 1.UDP协议格式 2.UDP的特点 3.面向数据报 4.UDP的缓冲区 5.UDP使用注意事项 6.UDP协议在内核中的表现形式 7.基于UDP的应用层协议 三.TCP协议 1.TCP协议格式 2.TCP确认应答机制 3.超时重传机制 4.TCP报文六位标志位 5.滑动窗口 6…

SpringBoot整合knife4j生成Api文档

一、介绍 先看效果 ①:Swagger 介绍 Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务(https://swagger.io/)。 它的主要作用是: 使得前后端分离开发更加方便,有利于团队协作 接口的文档…

Axios简单使用与配置安装-Vue

安装Axios npm i axios main.js 导入 import Axios from axios Vue.prototype.$axios Axios简单发送请求 get getTest() {this.$axios({method: GET,url: https://apis.jxcxin.cn/api/title?urlhttps://apis.jxcxin.cn/}).then(res > {//请求成功回调console.log(res)}…

从0开始学习JavaScript--JavaScript生成器

JavaScript生成器(Generator)是一项强大的语言特性,它允许函数在执行过程中被暂停和恢复,从而实现更灵活的控制流。本文将深入探讨JavaScript生成器的基本概念、用法,并通过丰富的示例代码展示其在实际应用中的优势和强…

Web应用系统的小安全漏洞及相应的攻击方式

1 写作目的 本文讲述一个简单的利用WebAPI来进行一次基本没有破坏力的“黑客”行为。 主要目的如下: 了解什么叫安全漏洞知道什么是api了解一些获取api的工具通过对API的认识了解白盒接口测试基本概念和技术 免责声明: 本文主要是以学习交流为目的…