数据结构

返回计算机基础

数据结构是组织和存储数据的方式,直接决定算法的时间与空间效率。选择合适的数据结构是解决问题的第一步。


复杂度速查

数据结构访问查找插入删除
数组O(1)O(n)O(n)O(n)
链表O(n)O(n)O(1)O(1)
栈/队列O(n)O(n)O(1)O(1)
哈希表O(1) 均摊O(1) 均摊O(1) 均摊
二叉搜索树(均衡)O(log n)O(log n)O(log n)O(log n)
O(1) 极值O(log n)O(log n)

数组(Array)

连续内存存储,支持 O(1) 随机访问。

索引:  0    1    2    3    4
       [10] [20] [30] [40] [50]
地址:  base  base+4  base+8 ...
  • 优点:随机访问快,缓存友好(空间局部性)
  • 缺点:插入/删除需移动元素;静态数组大小固定
  • 动态数组(Java ArrayList、Python list):扩容时分配 2 倍空间,均摊 O(1) 追加

链表(Linked List)

节点通过指针连接,不要求连续内存:

单向链表:[data|next] → [data|next] → [data|null]
双向链表:null ← [prev|data|next] ↔ [prev|data|next] → null
  • 优点:已知节点位置时插入/删除 O(1),无需预分配大小
  • 缺点:随机访问 O(n),额外指针开销,缓存不友好

栈(Stack)

LIFO(后进先出),只在栈顶操作:

push(x) → 压栈    pop() → 弹栈    peek() → 查看栈顶

应用:函数调用栈、括号匹配、表达式求值、DFS、浏览器后退。


队列(Queue)

FIFO(先进先出),队尾入队,队头出队:

变种说明
双端队列(Deque)两端均可入队/出队
优先队列按优先级出队,通常用堆实现
循环队列数组实现,避免假溢出

应用:BFS、任务调度、消息队列、滑动窗口。


哈希表(Hash Table)

通过哈希函数将键映射到数组索引,实现 O(1) 均摊查找:

key → hash(key) % capacity → 数组槽位 → value

哈希冲突解决

方法说明
链式法(Chaining)每个槽位存链表,冲突元素追加到链表
开放寻址(Open Addressing)冲突时探测其他槽位(线性/二次/双散列)

负载因子 = 元素数 / 数组容量,超过阈值(通常 0.75)触发扩容重哈希。


树(Tree)

二叉搜索树(BST)

左子树所有节点 < 根 < 右子树所有节点,中序遍历得到有序序列。有序插入会退化为链表,查找退化到 O(n),需平衡。

平衡 BST

类型说明特点
AVL 树严格平衡(左右子树高度差 ≤ 1)查找快,旋转多
红黑树近似平衡(黑高相等)插入/删除旋转少,Java TreeMap 使用
B/B+ 树多路平衡,减少磁盘 IO数据库索引(MySQL InnoDB)

堆(Heap)

完全二叉树,用数组存储(节点 i 的左子为 2i+1,右子为 2i+2):

  • 最大堆:父节点 ≥ 子节点,堆顶为最大值
  • 最小堆:父节点 ≤ 子节点,堆顶为最小值

应用:堆排序、优先队列、Top-K 问题、Dijkstra 算法。


图(Graph)

由顶点(Vertex)和边(Edge)组成,表示实体间关系。

存储方式

方式适用空间
邻接矩阵稠密图、快速判断两点是否相邻O(V²)
邻接表稀疏图、遍历邻居O(V+E)

遍历

  • BFS:借助队列,适合最短路径(无权图)
  • DFS:借助栈/递归,适合连通性、拓扑排序

跳表(Skip List)

在有序链表上建立多层索引,实现 O(log n) 查找:

Level 3:  1 ─────────────────── 9
Level 2:  1 ──────── 5 ──────── 9
Level 1:  1 ── 3 ── 5 ── 7 ── 9

Redis 的有序集合(ZSet)底层使用跳表实现。


相关链接