数据结构之基:从根儿上了解数据结构的特性

news2025/7/23 15:39:10

学好数据结构,就等于成功了一半。

程序是对现实的模拟,现实是由时间和空间组成的,高效的人都是用最少的时间、最少的空间来做最伟大的事,程序亦是如此。我们要选择最合理的算法和最合理的数据结构,来写最好的代码,这也正是时间复杂度和空间复杂度的要求。

所以,学好数据结构,选择合理的数据结构,降低时空复杂度,就等于成功了一半

我们可以将数据结构分为两大部分:线性数据结构和非线性数据结构。

  • 线性数据结构:数据元素之间的关系是一对一的。
  • 非线性数据结构:数据元素之间的关系不是一对一的。

线性数据结构

数据元素之间的关系是一对一的。可以简单地记忆为:一根绳子不分叉

这是嘛意思呢?

可以这么理解:我有一根绳子,上面打了好多结,我随便找到一个结点,不管往哪一端捋,都只能找到一个点,除非到头了导致没结点了。说白了就是:这根绳子没有分叉。

比如我们生活中的排队,就是这个模型。你前后最多都只有一个人,也就是:一对一的。

这个模型有很多衍生物,我们来逐个看下。

1. 顺序表

顺序表是紧密相邻的线性数据结构。便于查找元素,不便于插入和删除元素。

也就是说:顺序表的所有元素都是一个挨一个的。

比如军训时候的排队,所有人都在操场内;再比如核酸检测时的排队,所有人都在检测亭附近;前一个人挨着后一个人,紧密相邻。

所以,顺序表的特点就是:相邻

这样就有一个明显的特点,因为我们彼此是挨着的,那么就等于排好了队。那么,我只要知道某个人的位置,就能找到他。

那么,我们就可以根据这个特点给每个元素定个编号,然后根据编号直接找到对应的元素。如下图所示:

我们要找第 ii 个人,也就是 aiai​,直接去第 i−1i−1 位置即可,这样非常快,不用一个一个数。

那有人就说了,既然这么方便,我们直接全部用顺序表不就行了吗?不行!

这样找着是很快,但是,你发现了吗,如果少了一个元素,后面的所有元素都要往前挪一步;插入一个元素,后面所有元素都要往后挪一步。就像排队,有人插队和离队,后面所有人都要挪一步。

那么,能不能不挪呢?如果不挪,就留了个空位,那么空位前后的人就没有相邻元素了,那么就从空位开始断开了,那么就不是顺序表了。所以不行,必须挪!

综上所述,顺序表的特点就是:便于查找元素,不便于插入和删除元素!

那么,有没有啥法子能插入和删除时候不挪呢?这样就可以专门用来针对低素质群体了。

有,链表!

2. 链表

链表是非直接相邻的顺序表。便于插入删除,不便于查找。

链表跟顺序表是一对“杠精”,只要记住顺序表的特点,反过来就是链表的特点。顺序表的元素是一个挨一个的,链表就是不挨的。

有人可能会问了:这不对啊,不挨着怎么找到前一个或者后一个元素,要是找不到,就不是线性表了。

可以找到,就是要费点劲。

比如:我在北京,我爸爸在上海,不相邻,我能找到他吗?能啊,我直接根据地址开车过去就行了,虽然费劲,但是也能找到啊,并且这个地址也只能找到他啊。这也满足:一对一的关系

这找得也太费劲了,确实费劲。有人要找我,但他只有我爷爷的地址,就先找到了我爷爷,问他要了我爸的地址,然后找到了我爸要了我的地址,最后根据地址找到了我。

从这里可以看到,链表的查找步骤不是直接报个序号就行的,而是需要从头开始挨个往下找,所以查找费劲,也就不便于查找。

那么,为什么要这么设计呢?因为这样便于插入和删除。比如有一天,我爸去了国外,那么他只要把我的地址给我爷爷就行了,我和我爷爷都不需要搬家,这样找我的人,还是按照之前的步骤就行;如果有一天我爸回来了,那么他把他自己的地址给我爷爷,然后我把我自己的地址给他,就行了,仍然不需要搬家。如果是顺序表就惨了,估计搬家都搬吐血了。

从这里我们可以看到,链表的设计是不需要相邻的,它通过上一个元素持有下一个元素的地址来找到下一个元素,插入/删除时只需要改变地址即可,不需要挪动位置。这样非常便于插入和删除,但是不便于查找。

这样通过地址连起来,就像一条“链”一样,如下图所示:

如果我们删除了 aiai​,我们只需要将 ai−1ai−1​ 指向的地址改成 ai+1ai+1​ 即可。插入元素同理。

所以,链表的特点是:便于插入删除, 不便于查找。

3. 栈

栈是先进后出FILO)的线性结构。

栈是一种抽象的数据结构,它只要求元素满足先进后出,不要求你是怎么存放的。

比如只有一个门的公交车,第一个进去的最后才能出来;比如冰柜里的雪糕,第一个放进去的最后才被取出来;再比如碗里的饺子,第一个放进去的最后才被吃掉。

这些都有一个特点:只有一个口!因为只有一个口,所以导致最先进去的最后才出来,所以就叫先进后出,或者叫作 FILO(First In Last Out)。

那么,这有啥用呢?难不成就是专门用来模拟吃饺子的?非也!

因为栈是先进后出的,所以特别适合用来模拟历史的回溯,也就是说,逆流而上追溯历史,将历史“倒放”一遍。

历史的回放?这是啥?比如我们打开浏览器,打开一个个页面,我们关闭的一定是最后打开的,换句话说:最先打开的反而最后关闭。也就是说,如果我们打开的顺序是:A->B->C->D,那么我们关闭的顺序就是 D->C->B->A。

这给我们的感觉就是:将历史记录倒放了一遍。这正是栈的特点。

历史明明是“前天->昨天->今天”这样过来的,但是我们回到过去的话,却是“今天->昨天->前天”这样经过的,这就是对历史的回溯。

栈最常用的地方就是计算机的函数调用,不管何种语言,最先被调用的一定最后返回,比如:

functionA() {
  functionB();
}

functionB() {
  functionC();
}
  • 调用顺序是: functionA() -> functionB()-> functionC()
  • 返回顺序是: functiuonC() -> functioB()-> functionA()

functionC()最后被调用,却最先被执行完,然后把结果返回给functionB()functionB()再执行完毕返回,把结果返回给functionA()

这就是栈最常用的地方,所以我们经常说函数栈,也就是这个道理。

其实我们可以广义地概括一下栈的使用场景:具有对称性凡是具有对称性要求的场景,都优先考虑使用栈

比如上面的页面返回例子,A->B->C->D 和 D->C->B-A,这是以 D 为对称轴左右对称的。上面的函数调用,也是以functionC()为对称轴左右对称的。

换句话说:FILO 就是以最后进来(最先出去)的那个为对称轴左右对称的,凡是有这种要求的,都以优先考虑栈。

4. 队列

队列是先进先出FIFO)的线性结构。

队列是一种抽象的数据结构,它要求元素满足先进先出,不要求元素怎么存放。

比如两个门的公交车,前面进、后面出,那么先进入的人就会先出来;再比如汽车排队隧道,先进入的先出来。

它们也都有一个特点:两个口!因为两个口,一个进一个出,那么先进去的肯定先跑到出口,所以就叫先进先出,或者叫作 FIFO(First In First Out)。

可以看到,队列跟栈相反,更适合人们的思维,因为它是公平的!

它可以用于模拟日常的大部分操作,比如下载,先点击的就先下载,只有前面的下载完了才轮到后面的;再比如,12306 买票的候补,先点击候补的优先出票。

因为队列是先进先出的,所以就特别适合对历史的回放。也就是说,按照历史顺序,将历史“重新演绎一遍”。

比如:我们开发一个直播间,先进直播间的人肯定排在前面。这时候就可以使用队列。

因为队列是先进先出的,也是符合人们正常思维的,所以,凡是不需要使用栈的地方,都可以使用队列

非线性数据结构

数据元素之间的关系是一对多,或者多对多的。

非线性数据结构的关系可能是一对多,或者是多对多。一对多的我们称为;多对多的我们称为

1. 树

树是一对多的数据结构。适合有层级关系的场景。

我们知道,树只有一个根,但是却有多个分支,每个分支又有多个分支。这特别适合用来模拟分层的场景,比如组织结构图、大纲图,还有脑图。

最常见的场景就是分页了。

比如:从一亿个人中,找到一个名字叫张三的人(假设名字都不重复),怎么找呢?一个一个去对比名字是否叫张三吗?这太费劲了。

我们可以这样做:

  • 先按照名字个数分组,两个字名字的分到 A 组,三个字名字的分到 B 组,四个字名字的分到 C 组。
  • 针对每一组,再按照姓氏分,姓王的分到王组,姓张的分到张组。
  • 然后针对每个姓氏组,再按照名字的笔画分组,“三”有 3 笔,就被分到 3 组。

这样,我们就好找了。张三,两个字,去 A 组;姓张,去张组;名字是 3 笔,去 3 组。也就是,A 组的张组的 3 组。这里只有几千个人了,很好找了。

这里的整个一亿人就是一棵树,A 组、B 组、C 组分别是主枝干,王组、张组是次一级枝干,1 组、2 组、3 组又是次一级枝干,每个人都是一片叶子。

可以看到,有明显的层次关系,这样划分得更清晰,也更好找。

再比如,书的目录、部门的组织关系,等等,都很适合用树来表示。

到这里,我们总结下树的特点:一对多,有层级关系,适合分页。

2. 图

图是多对多的数据结构。适合没有层级的网状关系。

既然树适合有层级的场景,那么没有层级的呢,就可以用图了。

比如:手机联系人,我有我家人的、我朋友的,家人又有家人的,家人又有他们的朋友的……如此,就形成了一张大网,这张网里的所有人都是平等关系,又都是多对多的,这就适合用图来表示了。

假如我们要做一个城市的地图,或者要做一个朋友圈关系网,我们就可以采用图。

有人说,图是平级关系,那么我们的城市地图有拥挤程度,朋友圈也有重要朋友和不重要朋友,怎么表示呢?这个就可以使用加权图了,这是更详细的划分了,本章我们不做过多介绍。

这里说的“层级”,不是关系的重要程度,而是是否存在着主次关系,如果有了主次关系,那就不适合使用图了。

图的使用除了日常的模型模拟之外,还有路径规划、拓扑排序等很多场景,我们后面会细讲。

总结

本章从整体讲解了数据结构的划分,以及它们的特点和使用场景,有点流水账的味道。我们再来梳理和回顾一下。

  • 线性数据结构:元素之间是一对一的关系。
  • 非线性数据结构:元素之间是一对多或多对多的关系。
  • 顺序表:紧密相邻的线性数据结构,便于查找,不便于插入删除。
  • 链表:不相邻的线性数据结构,便于插入删除,不便于查找。
  • 栈:先入后出的线性数据结构,适合对历史的回溯。
  • 队列:先入先出的线性数据结构,适合对历史的回放。
  • 树:一对多的非线性数据结构,适合有层级关系的场景。
  • 图:多对多的非线性数据结构,适合无层级关系的场景。

我们这部分讲的内容都是抽象的,并不涉及具体的实现,因为我们只有先从顶层了解了它们的概念和特点后,再带着这些已有理解去看具体实现会有更深刻的印象,记得也更牢。后面我们就从具体的实现来看一下每一种数据结构的具体使用场景以及在代码中的精彩表现。

程序员的必修课 - 奔波儿灞取经 - 掘金小册数据结构+计算机网络+操作系统+设计模式,软硬兼修,深入浅出带你夯实程序员基本功。「程序员的必修课」由奔波儿灞取经撰写,610人购买https://s.juejin.cn/ds/BoPu7q4/

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

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

相关文章

MySQL进阶知识

1 存储引擎1.1 MySQL体系结构1.2 存储引擎简介存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,同一个库的多个表可以采用不同的存储引擎,所以存储引擎也经常称为表类型。创建表时可以指…

Rocketmq源码(一)手把手本地调试

很久没有学习了,从前是因为太忙,现在是因为太懒。立个flag,一定要把rocketmq源码看完!源码阅读从idea的环境搭建和debug开始~ Idea搭建调试目录代码下载代码架构启动namesvr启动broker启动consumer启动producer代码下载…

深度学习训练营之yolov5 官方代码调用以及-requirements.txt下载当中遇到的问题

深度学习训练营之yolov5 官方代码调用原文链接内容总结环境介绍前置工作简单介绍yolov5下载源码yolov5的下载遇到问题问题解析问题处理创建虚拟环境下载当中遇到的问题代码运行视频检测参考内容原文链接 🍨 本文为🔗365天深度学习训练营 中的学习记录博客…

taobao.trades.sold.query( 根据收件人信息查询交易单号 )

¥开放平台免费API必须用户授权聚石塔内调用 根据收件人信息查询交易单号。 公共参数 请求地址: HTTP地址 公共请求参数: 公共响应参数: 请求参数 请求示例 TaobaoClient client new DefaultTaobaoClient(url, appkey, secret); TradesSoldQueryRequest req new…

我用了33行纯CSS实现了下划线的交互动画效果

背景 最近看到了一个特别炫酷的网站上的一个小细节,下划线的动画。看下他的实现效果。 但是,假如我们左边并没有足够的空间存放一条不可见的下划线呢? 像这样。 思路与实现 我要把这个下划线也做成文章刚开始的动画。就不是太好借鉴上面的思…

Windows Server 2022 中文版、英文版下载 (updated Feb 2023)

Windows Server 2022 中文版、英文版下载 (updated Feb 2023) Windows Server 2022 正式版,2023 年 2 月更新 请访问原文链接:https://sysin.org/blog/windows-server-2022/,查看最新版。原创作品,转载请保留出处。 作者主页&a…

Spring Boot 调取Bartender使用教程

Spring Boot 调取Bartender使用教程.md 原文链接:小回博客 博主可帮忙配置bartender进行打印,另有完整Mes系统源码。业务清单 文章目录Spring Boot 调取Bartender使用教程.md[toc]一、复制解压压缩包JavaBarTenderPrint.zip到C盘根目录下:二…

DNF搭建服务器服务端搭建教程

DNF搭建服务器服务端搭建教程 我是艾西,今天给大家分享下怎么样自己搭建一个DNF。 前阵子体验了下其他GM搭建的服,那么对于自己搭建的好处在于出道即巅峰! 想要什么武器就是一串代码命令的事情。 下面我跟大家说一下需要准备那些东西&#x…

2023年度数学建模竞赛汇总

本人7年数学建模竞赛经验,历史获奖率百分之百。团队成员都是拿过全国一等奖的硕博,有需要数模竞赛帮助的可以私信我。 下面主要列几年一些比较有含金量的数学建模竞赛(按比赛时间顺序) 1. 美国大学生数学建模竞赛 报名时间&…

mars3d基础项⽬常⻅报错

1.在⼤家使⽤mars3d基础项⽬的时候经常遇到这个报错,截图如下 回答: 1.原因是因为使⽤了cnpm安装依赖,导致了⼀些依赖问题 2.解决⽅式也很简答,重新使⽤ npm 或 yarn 或 pnpm安装依赖即可 2.本地加载地图时,出现报错回…

云原生|kubernetes|ingress-nginx插件部署(kubernetes-1.23和最新版controller-1.6.4)

前言: ingress是kubernetes内的一个重要功能插件,这个使得服务治理成为一个可能,当然,结合微服务更为妥当了。 不管是什么插件,还是服务,第一步当然是要能顺利的部署到系统当中,这样&#xff…

Oracle——物化视图

文章目录含义物化视图的语法物化视图的创建1、自动刷新的物化事务 ON COMMIT2、非自动刷新的物化视图 ON demand关于手动刷新物化视图的删除资料参考含义 什么是物化视图? 物化视图,通俗点说就是物理化的视图。 什么叫物理化? 将视图以表结构…

【论文解读】如何使用1B参数的小模型打败GPT3.5

大型语言模型 (LLM) 通过利用思维链 (CoT) 提示生成中间推理链作为推断答案的基本原理,在复杂推理上表现出了令人印象深刻的性能。 然而现有的 CoT 研究主要集中在语言模态上。 我们提出 Multimodal-CoT(多模态思维链推理模型),它…

GCC:从源文件到可执行文件

GCC&#xff1a;从源文件到可执行文件 假设我们有hello.c 文件 #include <stdio.h> int main(){printf("hello world!\n");return 0; }怎么在linux上利用GCC命令生产可执行文件&#xff08;单文件编译&#xff09;呢&#xff1f; 一、流程 C文件从源文件到…

二极管温度补偿电路工作原理分析

众所周知&#xff0c;PN结导通后有一个约为0.6V&#xff08;指硅材料PN结&#xff09;的压降&#xff0c;同时PN结还有一个与温度相关的特性&#xff1a;PN结导通后的压降基本不变&#xff0c;但不是不变&#xff0c;PN结两端的压降随温度升高而略有下降&#xff0c;温度愈高其…

Git天天用,不得不看的那些事

作为一个工作两年的开发同学&#xff0c;git是每天都要接触的工具。但IDEA对git的封装已经满足了日常的代码提交需求&#xff0c;所以一直是以点点点的形式进行代码提交与更新&#xff0c;几乎没用命令行提交过&#xff08;现在想来也是有些惭愧&#xff09;&#xff0c;对于gi…

【华为OD机试模拟题】用 C++ 实现 - 环中最长子串(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

VMware ESXi 7.0 U3k Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

ESXi 7 U3 标准版集成 Intel 网卡、USB 网卡 和 NVMe 驱动 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3-sysin/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 本次针对 2023-02-21 发布的 ESXi …

Tina_Linux_系统软件 开发指南

Tina_Linux_系统软件 开发指南 1 概述 编写目的&#xff1a;本文档作为Allwinner Tina Linux系统平台开发指南&#xff0c;旨在帮助软件开发工程师、技术支持工程师快速上手&#xff0c;熟悉Tina Linux系统的开发及调试流程。 适用范围&#xff1a;Tina Linux v3.5及以上版本…

5.35 综合案例2.0 -称重数据上传云端

综合案例2.0 - 称重数据上传云端案例说明连线功能实现1.阿里云平台连接代码应用开发3.1新建‘普通项目’3.2关联产品和设备3.3新建‘移动应用’3.4添加组件3.5配置组件信息3.6保存预览案例说明 使用hx711串口模块称重,结合IOT studio制作手机APP远程控制并采集物体重量。 hx7…