当前位置: 首页 > news >正文

【追求卓越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缓存机制更加友好。

相关文章:

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

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

qt按照不同编码格式读取文字(UTF-16LE,UTF-8,UTF-8BOM,UTF-16BE)

enum class EncodingFormat : int {ANSI 0,//GBKUTF16LE,UTF16BE,UTF8,UTF8BOM, }; EncodingFormat VideoPlayer::FileCharacterEncoding(const QString &fileName) {//假定默认编码utf8EncodingFormat code EncodingFormat::UTF8;QFile file(fileName);if (file.open(QI…...

R语言和RStudio的下载安装(非常简便舒适)

目录 R语言和RStudio的关系R语言和Tableau下载R语言进入官网选择清华镜像源Download R for Windows选择base版本开始下载进行安装配置环境变量检查是否安装成功 下载RStudio进入官网点击下载进行安装检查是否安装成功打开选择R语言环境成功打开显示四个工作区 R语言和RStudio的…...

SQL注入漏洞发现和利用,以及SQL注入的防护

一、背景 SQL注入漏洞是一种常见的软件安全问题,它发生在应用程序的数据库层中。其核心原理是将用户输入的数据当做代码来执行,违反了“数据与代码分离”的原则。具体来说,攻击者通过构造恶意的SQL查询语句,使得应用程序在执行SQ…...

Jmeter 分布式压测

为什么要分布式 jmeter是100%纯java开发的程序,虚拟用户是以线程实现的,在大量并发情况下,很容易出现CPU、内存消耗过大的问题,甚至会出现java内存溢出。一般一台电脑设置500-600线程数即可,如果超过1000线程&#xf…...

Docker 安装 Apache

目录 拉取官方 Apache 镜像 查看本地镜像 列出正在运行的容器 运行 Apache 容器 创建一个 HTML 文件:index.html 访问 Apache 拉取官方 Apache 镜像 查找 Docker Hub 上的 httpd 镜像。 可以通过 Tags 查看其他版本的 httpd,默认是最新版本 httpd…...

python变量、常量、数据类型

一、变量 变量是存储在内存中的值,这就意味着在创建变量时会在内存中开辟一个空间。 基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中。 因此,变量可以指定不同的数据类型,这些变量可以…...

注册中心CAP架构剖析

Nacos 支持 AP 或 CP AP Nacos 通过临时节点实现 AP 架构,将服务列表放在内存中; CP Nacos 通过持久化节点实现 CP 架构,将服务列表放在文件中,并同步到内存,通过 Raft 协议算法实现; 通过配置 epheme…...

SVN创建分支

一 从本地创建方式可指定版本号进行分支创建。 1、在本地目录右击 -----> 点击branch/tag(分支/标签) From: 源,可指定具体的版本号, To path: 可通过"..."选择分支路径 最后点击确定,交由服务器执行创建。 二 通过SVN客…...

Vue 设置v-html中元素样式

使用方式&#xff1a; <<< img { max-width: 100% } 如&#xff1a;要将v-html中的图片元素(img)的最大宽度设置为100%. <template><div ><div class"rtfDiv book" v-html"content"></div></div> </template&…...

连接服务器的脚本

对于记不住的服务器密码且不愿用三方工具俺简单写了个脚本&#xff08;检测下最近shell脚本的学习效果咋样&#xff09; expect 是处理交互的一种脚本语言&#xff0c;spawn启动指定进程 -> expect获取指定关键字 -> send想指定进程发送指定指令 -> 执行完成后退出 sp…...

ChatGPT/GPT4丨编程助手;AI画图;数据分析;科研/项目实现;提示词工程技巧;论文写作等

ChatGPT 在论文写作与编程方面也具备强大的能力。无论是进行代码生成、错误调试还是解决编程难题&#xff0c;ChatGPT都能为您提供实用且高质量的建议和指导&#xff0c;提高编程效率和准确性。此外&#xff0c;ChatGPT是一位出色的合作伙伴&#xff0c;可以为您提供论文写作的…...

35的程序员被辞了可以自己接外包啊?为什么都那么悲观呢?

35的年纪&#xff0c;上有老下有小&#xff0c;即将步入中年危机&#xff0c;在这个节骨眼上被辞&#xff0c;能不悲观吗&#xff1f; 在这个年纪人们往往追求的是稳定的工作和生活&#xff0c;而进入一个自己不熟悉的行业并不是一个好的选择。 况且&#xff0c;你认为的外包…...

2020年09月 Scratch(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 执行下面程序,屏幕上最多会看到多少个苹果? A:10个 B:11个 C:1个 D:无法确定 答案:B 第2题 关于下面程序,说法正确的是 ? A:执行 后,马上执行...

SpringBoot面试之SpringBoot自动装配原理

SpringBoot自动装配原理 背景 最近因为各种原因&#xff0c;我又重新加入到了找工作的大军当中。昨天在面试的时候与面试官聊到我们项目都是基于SpringBoot开发的&#xff0c;然后面试官就顺口问了句&#xff1a;”SpringBoot项目会引入许多的starter&#xff0c;比如&#x…...

JavaScript:监听事件

该方法用于向浏览器窗口注册事件监听器&#xff0c;当指定的事件&#xff08;如单击、按键按下&#xff09;被触发时&#xff0c;浏览器会自动调用指定的函数&#xff08;回调函数&#xff09;。 window.addEventListener(event, function, useCapture); 参数说明&#xff1a…...

编写SQL语句,场景:从一张表中查询某字段是逗号分隔的集合值,需要遍历集合内每个值,将其作为条件去查询另一张表,最终返回列表

目录 场景编写SQL分页获取该开票单号下的所有订单列表使用子查询和 in 字句使用 find_in_set 场景 从一张表中查询某字段是逗号分隔的集合值&#xff0c;需要遍历集合内每个值&#xff0c;将其作为条件去查询另一张表&#xff0c;最终返回列表 编写SQL 分页获取该开票单号下…...

单链表相关面试题--7.链表的回文结构

7.链表的回文结构 链表的回文结构_牛客题霸_牛客网 (nowcoder.com) /* 解题思路&#xff1a; 此题可以先找到中间节点&#xff0c;然后把后半部分逆置&#xff0c;最近前后两部分一一比对&#xff0c;如果节点的值全部相同&#xff0c;则即为回文。 */ class PalindromeList…...

JUC(Java Util Concurrent)多线程并发库

JUC&#xff08;Java Util Concurrent&#xff09;是Java中用于编写多线程并发程序的库。开发过程中使用JUC主要有以下几个好处&#xff1a; 1. 提高程序性能&#xff1a;使用JUC可以实现多线程并发执行&#xff0c;充分利用多核CPU&#xff0c;提高程序的性能。 2. 简化代码…...

如何在Linux系统上检测GPU显存和使用情况?

如何在Linux系统上检测GPU显存和使用情况&#xff1f; 在Linux系统上&#xff0c;你可以使用一些命令行工具来检测GPU显存和使用情况。以下是一些常用的方法&#xff1a; 1. 使用nvidia-smi&#xff08;仅适用于NVIDIA GPU&#xff09; 如果你使用的是NVIDIA的显卡&#xff0…...

基于vue的鲜花销售网站[vue]-计算机毕业设计源码+LW文档

摘要&#xff1a;随着互联网技术的发展和人们消费习惯的改变&#xff0c;线上鲜花销售市场前景广阔。本文介绍了一个基于Vue框架开发的鲜花销售网站&#xff0c;详细阐述了其设计目标、采用的相关技术、需求分析、系统设计以及具体的实现过程。该网站实现了用户管理、商品展示与…...

MacBook Air M5 免费养个 AI 助手:Gemma 4 本地运行 OpenClaw 完全指南

一条命令&#xff0c;5 分钟搞定。本地运行&#xff0c;完全免费&#xff0c;微信随时对话。 先说结论 我用 MacBook Air 13 M5 测试了一整天&#xff0c;结论&#xff1a; ✅ Gemma 4 E4B 本地运行&#xff1a; 流畅&#xff0c;响应 2-4 秒✅ **完全免费: 不花一分钱✅ **隐…...

ROS新手必看:用USB摄像头和image_transport实现实时图像传输(附完整代码)

ROS实战&#xff1a;从零搭建USB摄像头图像传输系统 第一次接触ROS的视觉开发时&#xff0c;最让人兴奋的莫过于让机器人"看见"周围环境。而这一切的起点&#xff0c;往往是从一个小小的USB摄像头开始。本文将带你完整实现一个可运行的ROS图像传输系统&#xff0c;涵…...

云原生应用测试策略:从单元测试到端到端测试

云原生应用测试策略&#xff1a;从单元测试到端到端测试 一、云原生测试的概念与价值 1.1 云原生测试的定义 云原生测试是针对云原生应用的测试策略和方法&#xff0c;它考虑了容器化、微服务架构、动态伸缩等云原生特性&#xff0c;旨在确保应用在云环境中的可靠性、性能和安全…...

PHP+AI代码审计实战手册(2024 OWASP Top 10适配版)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;PHPAI代码审计的范式变革与安全挑战 传统PHP代码审计长期依赖人工规则匹配与经验驱动&#xff0c;面对现代框架&#xff08;如Laravel、Symfony&#xff09;的动态路由、魔术方法和反射调用&#xff0c…...

PHP安全那些坑:从PolarCTF靶场看RCE绕过与变量覆盖的防御之道

PHP安全实战&#xff1a;从CTF靶场解析RCE与变量覆盖的防御策略 在2023年OWASP发布的十大Web应用安全风险中&#xff0c;注入类漏洞依然高居榜首。作为占据全球78%网站服务端的语言&#xff0c;PHP的代码安全问题直接影响着数百万线上业务。上周在审查某金融平台代码时&#xf…...

软件交互式查询化的即时反馈与探索

在数字化时代&#xff0c;软件交互式查询化的即时反馈与探索正成为提升用户体验和效率的关键技术。无论是数据分析工具、搜索引擎&#xff0c;还是智能客服系统&#xff0c;用户都期望通过快速、直观的交互获得精准的反馈。这种技术不仅缩短了信息获取的路径&#xff0c;还让复…...

Godot4.2进阶:用SurfaceTool从画一个三角面到生成自定义3D模型(避坑指南)

Godot4.2进阶&#xff1a;用SurfaceTool从画一个三角面到生成自定义3D模型&#xff08;避坑指南&#xff09; 在游戏开发中&#xff0c;3D模型的程序化生成是一个既令人兴奋又充满挑战的领域。Godot引擎的SurfaceTool类为我们提供了一把打开这扇大门的钥匙&#xff0c;它允许开…...

别再手动补类了!Spring Boot 2.6 与 Nacos 2.0.3 版本冲突的三种解法实测

Spring Boot 2.6与Nacos 2.0.3版本冲突的深度解决方案剖析 当Spring Boot 2.6遇上Nacos 2.0.3&#xff0c;不少开发者都遭遇过那个令人头疼的NoClassDefFoundError异常。这个问题看似简单&#xff0c;实则涉及框架版本兼容性、依赖管理、类加载机制等多个技术维度。本文将带你深…...

不止于中文:为你的LVGL项目轻松添加多语言支持(RTL文本+FreeType动态字体加载)

智能设备多语言UI实战&#xff1a;LVGL集成RTL语言与动态字体加载全方案 当智能家居控制面板需要同时显示阿拉伯语和中文时&#xff0c;工程师们往往会遇到文字方向混乱、字体缺失和内存暴增三大难题。去年为迪拜某酒店项目开发温控系统时&#xff0c;我们团队就曾因阿拉伯语连…...