哲学里有一句很经典的话,”下层基础决定上层建筑“。相信很多人都听过,广泛用于我们生活中。
那么我们软件开发行业的下层基础是什么,有人说是操作系统、是网络、是HTTP协议、是TCP,这些虽然也是底层,但其实不够原子化。
软件行业讲究的是抽象,那么他们的共同点是什么。那就是数据和计算。

数据不是幽灵,需要有个载体,今天这节,我们就来讲下数据有哪些存储结构。

1、数组
定义:
数组是一组连续内存空间存储的具有相同类型的数据,整个排列像一条线一样,是一种线性表数据结构。

划重点:
像常见的数组、链表、栈、队列,都是线性结构。
优势:
随机访问。为什么呢?因为他的类型固定,决定它的数据长度也就固定,另外就是连续,所以基于初始地址,可以直接计算出数组任意位置的内存地址。查询速度很多。
缺点:
ArrayList相关API的源码链表注意点:
2、链表
定义:
链表一种非连续、非顺序的存储结构,由一系列节点组成,节点间通过指针完成了串联,每个节点包含数据和下一个节点指针两部分。

根据指针的方向可以分为:
划重点:
优势:
缺点:
随机存取注意点:
数组擅长按下标随机访问,链表擅长插入、删除操作。平常大家使用时,根据具体使用场景是读多还是写多灵活选择。
3、栈
定义:
又名堆栈,它是一种运算受限的线性表。上面成为栈顶,下面称为栈底。向栈插入新元素称为入栈,新元素放到栈顶;从一个栈删除元素又称作出栈,它是把栈顶元素删除掉,使其下面相邻的元素成为新的栈顶元素。

根据底层结构不同,可以分为数组实现的顺序栈、链表实现的链式栈。
划重点:
优势:
缺点:
典型场景:
4、队列
定义:
队列是一种特殊的线性表,只允许在表的前端进行删除操作,而在表的后端进行插入操作。和栈一样,队列是一种操作受限制的线性表。插入的数据放在队尾,读取数据的端称为队头。队列中没有元素时,称为空队列。

根据支持的高级特性,可以分为:循环队列、阻塞队列、并发队列。根据底层结构不同,可以分为顺序队列、链式队列。
划重点:
优势:
缺点:
典型场景:
ThreadPoolExecutor,来不及处理的任务会临时放在任务队列中5、哈希表
定义:
哈希表(Hash table)也叫散列表。根据键(Key)而直接访问在内存储存位置的数据结构。它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,加快查找速度。这个映射函数称为散列函数,存放记录的数组称做散列表。

划重点:
优势:
缺点:
可能存在哈希冲突,在每个冲突处构建链表,将所有冲突值链入链表。如果是恶意攻击,哈希表可能会退化为链表,所有元素都被存储在同一个节点的链表中,此时哈希表的查找速度=链表遍历查找速度=O(n)
为了描述冲突,引入装载因子=哈希表中的元素个数 / 哈希表长度,装载因子越大,说明链表的长度越长,性能会越低。
当装载因子过大时,需要动态扩容。申请一个更大的哈希表,将原哈希表的数据迁移到新的哈希表。
典型场景:
6、图
定义:
图(Graph)是由顶点的有穷非空集合和顶点之间的集合组成,通常表示为:G(V, E),其中 G 表示一个图,V 是图 G 中顶点的集合,E 是图 G 中边的集合。

上图是一个有向图G,G=(V,E),其中顶点集合 V = 1、2、3、4,边集合是 E = (1,3)、(2,1)、(2,4)、(3,2)、(3,4)、(4,2)
根据图是否有方向、权重等可以分为:有向图、无向图、带权图
划重点:
优势:
缺点:
任意点都可以建立关系,所以数据量会比较大。为了便于存储,我们将图用多维数组表示,从而将很多图运算转换为矩阵运算。
当然,如果图比较稀疏的话,可以采用邻接表的存储方式,与哈希表类似,可以节省很多空间。
典型场景:
注意:
7、树
定义:
顾名思义,跟现实的树一样,树上的每一个元素成为节点,节点与节点之间有一定的关系,上下称为父子节点,左右称为兄弟节点。

按照树的表现结构,可以具体分为以下几种类型:二叉树、平衡二叉树、满二叉树、完全二叉树、递归树、红黑树、B- 树、B+ 树 ,等
划重点:
优势:
缺点:
树中删除一个节点操作较复杂,需要根据其子节点的个数(0、1、2)分多种情况考虑,迁移部分节点,重新构造树结构。当然,也可以采用逻辑标记删除,物理空间没有释放,但会产生碎片,影响查询效率。
注意点:
8、堆
定义:
一种特殊的二叉树。需要满足两个条件:1、是一棵完全二叉树 2、堆中每个节点的值必须>=或<=其左右子节点的值。

具体,根据每个节点的值是>= 还是 <= 子树中每个节点的值,分为大顶堆、小顶堆。
划重点:
优势:
缺点:
典型场景:
示例:从10亿个数据中找到最大的前10个?

推荐阅读
原文作者:微观技术;如有侵权,请联系管理员删除。