常用的数据结构及其特点
数据结构是软件设计的基础,不同的数据结构适用于不同的场景。以下是常见的数据结构及其特点:
1. 数组(Array)
特点:
- 连续内存存储:元素按顺序存储在内存中,地址连续。
- 随机访问:可通过索引(下标)直接访问元素,时间复杂度 O(1)。
- 固定大小:大多数语言中数组长度不可变(如 C、Java),部分语言支持动态数组(如 Python 的
list
)。 - 插入/删除效率低:插入或删除元素需要移动后续元素,时间复杂度 O(n)。
适用场景:
- 需要频繁随机访问数据的场景(如查找、遍历)。
- 元素数量固定且已知的情况。
2. 链表(Linked List)
特点:
- 非连续存储:元素通过指针(引用)连接,内存不连续。
- 动态大小:可动态增减元素,无需预先分配内存。
- 插入/删除高效:只需修改指针,时间复杂度 O(1)(已知节点位置时)。
- 随机访问低效:需从头遍历,时间复杂度 O(n)。
分类:
- 单向链表:每个节点只有指向下一个节点的指针。
- 双向链表:每个节点有指向前驱和后继的指针。
- 循环链表:尾节点指向头节点,形成环。
适用场景:
- 频繁插入/删除数据的场景(如实现队列、栈)。
- 不需要随机访问的场景。
3. 栈(Stack)
特点:
- 后进先出(LIFO):最后插入的元素最先被移除。
- 操作限制:仅支持在栈顶插入(
push
)和删除(pop
)。 - 时间复杂度:
push
、pop
、peek
均为 O(1)。
实现方式:
- 可用数组或链表实现。
适用场景:
- 函数调用栈(保存函数调用上下文)。
- 表达式求值(如括号匹配、后缀表达式计算)。
- 撤销操作(如编辑器的撤销功能)。
4. 队列(Queue)
特点:
- 先进先出(FIFO):最先插入的元素最先被移除。
- 操作限制:仅支持在队尾插入(
enqueue
)和队头删除(dequeue
)。 - 时间复杂度:
enqueue
、dequeue
均为 O(1)。
分类:
- 普通队列:FIFO。
- 双端队列(Deque):支持两端插入和删除。
- 优先队列(Priority Queue):元素按优先级排序(如最小堆、最大堆)。
适用场景:
- 任务调度(如操作系统进程调度)。
- 消息队列(如 RabbitMQ、Kafka)。
- 广度优先搜索(BFS)。
5. 哈希表(Hash Table)
特点:
- 键值对存储:通过键(Key)快速查找值(Value)。
- 平均时间复杂度:插入、删除、查找均为 O(1)(依赖哈希函数和冲突解决策略)。
- 冲突处理:常用链地址法(链表存储冲突元素)或开放寻址法。
适用场景:
- 快速查找、插入、删除的场景(如字典、缓存)。
- 实现关联数组(如 Python 的
dict
、Java 的HashMap
)。
6. 树(Tree)
特点:
- 层次结构:节点之间有父子关系,根节点无父节点,叶子节点无子节点。
- 常见类型:
- 二叉树:每个节点最多有两个子节点。
- 二叉搜索树(BST):左子树节点值 < 根节点值 < 右子树节点值。
- 平衡二叉树(AVL、红黑树):保持左右子树高度平衡,保证操作时间复杂度为 O(log n)。
- B树/B+树:用于数据库和文件系统索引。
适用场景:
- 层次化数据存储(如文件系统、组织结构)。
- 快速查找、插入、删除(如数据库索引、搜索引擎)。
7. 堆(Heap)
特点:
- 完全二叉树:除了最后一层,其他层节点填满,最后一层靠左排列。
- 分类:
- 最大堆:父节点值 ≥ 子节点值(根节点最大)。
- 最小堆:父节点值 ≤ 子节点值(根节点最小)。
- 时间复杂度:
- 插入、删除:O(log n)。
- 获取堆顶元素:O(1)。
适用场景:
- 优先队列(如 Dijkstra 算法、任务调度)。
- 堆排序(时间复杂度 O(n log n))。
- Top K 问题(如找出最大的 K 个数)。
8. 图(Graph)
特点:
- 节点和边组成:节点(Vertex)通过边(Edge)连接。
- 分类:
- 有向图/无向图:边是否有方向。
- 加权图/非加权图:边是否有权重。
- 存储方式:
- 邻接矩阵:适合稠密图(节点多、边多)。
- 邻接表:适合稀疏图(节点多、边少)。
适用场景:
- 社交网络(用户关系)。
- 路径规划(如地图导航)。
- 网络拓扑(如路由器连接)。
9. 字典树(Trie,前缀树)
特点:
- 树形结构:用于高效存储和检索字符串集合。
- 特点:
- 共享公共前缀,节省空间。
- 查找、插入、删除时间复杂度为 O(m)(m 为字符串长度)。
- 变种:
- 后缀树:用于字符串匹配(如 KMP 算法)。
适用场景:
- 自动补全(如搜索引擎输入建议)。
- IP 路由表(网络设备)。
- 单词搜索(如拼写检查)。
10. 并查集(Disjoint Set Union, DSU)
特点:
- 动态连通性管理:高效处理集合的合并与查询。
- 操作:
find
:查找元素所属集合(路径压缩优化)。union
:合并两个集合(按秩合并优化)。
- 时间复杂度:接近 O(1)(优化后)。
适用场景:
- 动态连通性问题(如图的连通分量)。
- Kruskal 最小生成树算法。
- 网络连接检测(如社交网络好友关系)。
总结对比
数据结构 | 特点 | 适用场景 |
---|---|---|
数组 | 连续存储,随机访问快 | 固定大小数据,频繁随机访问 |
链表 | 动态大小,插入/删除快 | 频繁增删,不需要随机访问 |
栈 | LIFO,操作受限 | 函数调用、撤销操作 |
队列 | FIFO,操作受限 | 任务调度、BFS |
哈希表 | 键值对,快速查找 | 字典、缓存 |
树 | 层次结构,支持快速查找 | 文件系统、数据库索引 |
堆 | 完全二叉树,支持优先级操作 | 优先队列、堆排序 |
图 | 节点和边组成 | 社交网络、路径规划 |
字典树 | 共享前缀,高效字符串检索 | 自动补全、IP 路由 |
并查集 | 动态连通性管理 | 图的连通分量、最小生成树 |
选择建议:
- 需要 快速随机访问 → 数组。
- 需要 频繁增删 → 链表。
- 需要 LIFO/FIFO → 栈/队列。
- 需要 键值对快速查找 → 哈希表。
- 需要 层次化数据 → 树。
- 需要 优先级操作 → 堆。
- 需要 字符串检索 → 字典树。
- 需要 动态连通性 → 并查集。