写这篇文章主要是想简单综述一下数据结构里的底层逻辑。整篇文章没有对源码的分析,只是把这些概念同生活中的具体实例简单类比一下,方便理解。先上图:

一、内存里的两种积木
想象一下,内存就像一个巨大的乐高玩具箱,我们有两种积木可以用来搭建东西:
1. 数组:整齐排列的储物格
数组就像是超市里的一排储物格,每个格子都编了号,而且紧紧挨在一起。这种结构的好处是:
- 找东西快:只要知道编号(索引),直接就能找到对应的格子
- 省空间:格子之间没有空隙,内存利用率高
- 缺点:如果中间的格子要拿走或者添加东西,后面的格子都得跟着挪动
2. 链表:用绳子串起来的珠子
链表就像是用绳子串起来的珠子,每个珠子上都写着下一个珠子在哪里。这种结构的好处是:
- 灵活插入:想在哪里加珠子或者减珠子,直接剪断绳子就行
- 动态扩展:珠子不够了随时可以加,不需要提前准备很多
- 缺点:找特定的珠子得从头开始一个一个数
二、基于这两种积木的玩法
有了这两种积木,我们可以玩出不同的花样。最常见的两种玩法就是栈和队列,它们代表了两种不同的游戏规则。
1. 栈:像叠盘子一样的游戏
栈这个东西,就像是我们在家里叠盘子。最后放上去的盘子,总是第一个被拿走:
- 后进先出(LIFO):最后放进去的东西最先出来
- 只能操作顶部:就像叠盘子,只能从最上面拿或者放
数组栈:固定大小的盘子架
如果用数组来实现栈,就像是有一个固定大小的盘子架:
- 优点:操作简单,不需要额外的空间
- 缺点:盘子架满了就放不下了,得换一个更大的架子
链表栈:无限扩展的盘子链
如果用链表来实现栈,就像是用绳子串盘子:
- 优点:盘子可以无限加,只要有足够的绳子和盘子
- 缺点:每个盘子都得额外拴一根绳子,有点浪费
2. 队列:像排队一样的游戏
队列就像是我们在超市排队结账,先到的人先结账:
- 先进先出(FIFO):第一个排队的人第一个离开
- 两头操作:一头进人,一头出人
数组队列:循环使用的排队通道
用数组实现队列时,为了不浪费空间,我们可以把排队通道设计成循环的:
- 就像操场的跑道,跑完一圈可以接着跑下一圈
- 需要两个指针,一个指向队头,一个指向队尾
链表队列:灵活伸缩的排队链
用链表实现队列时,排队的人可以随时加入或者离开:
- 优点:队伍可以无限长,只要有足够的空间
- 缺点:每个人都得知道下一个人是谁,有点麻烦
三、实际场景中的选择
在实际编程中,我们怎么选择用哪种实现方式呢?这得看具体情况:
1. 数组实现的场景
- 如果我们知道最多会有多少个元素,比如扑克牌只有54张
- 如果我们需要频繁地随机访问元素,比如查字典
- 如果内存比较紧张,需要高效利用空间
2. 链表实现的场景
- 如果元素数量不确定,比如网站的访问日志
- 如果需要频繁地插入和删除元素,比如编辑器的撤销操作
- 如果内存不是问题,更看重操作的灵活性
四、扩展玩法
除了基本的栈和队列,我们还可以玩出更多花样:
1. 双端队列:两头都能操作的队列
双端队列就像是一个可以两头进出的隧道,既可以从前面进,也可以从后面进。
2. 优先级队列:VIP优先的队列
优先级队列就像是机场的VIP通道,有特权的人可以优先通过。
3. 并发队列:多个人同时操作的队列
在多线程编程中,我们经常需要多个线程同时操作一个队列,这时候就需要特殊的并发队列。
五、总结

通过这篇文章,我们用大白话解释了数据结构的底层逻辑:
- 数组和链表是内存中的两种基本存储方式
- 栈和队列是基于这两种存储方式的逻辑抽象
- 不同的实现方式有不同的优缺点,适用于不同的场景
理解这些底层逻辑,就像是掌握了编程世界的基本法则。在实际开发中,我们可以根据具体需求选择最合适的数据结构,从而写出高效、优雅的代码。希望这篇文章能帮助你更好地理解数据结构,谢谢阅读!
1万+

被折叠的 条评论
为什么被折叠?



