各数据结构操作的时间复杂度汇总

结论放在前面

数据结构 底层实现 查找 插入 删除 排序
数组 连续内存 O(1) 访问 / O(n) 搜索 O(n) O(n) O(n log n)​(快排/归并/堆排)
动态数组 连续内存 + 扩容 O(1) 访问 / O(n) 搜索 O(1) (末尾)/O(n) O(n) O(n log n)​(原地排序,同数组)
链表 节点 + 指针 O(n) O(1) O(1) O(n log n)​(归并排序,链表友好)
数组或链表 O(n) O(1) O(1) O(n log n)​(需先转存到数组)
队列 链表或循环数组 O(n) O(1) O(1) O(n log n)​(需先转存到数组)
哈希表 数组 + 链表/树 平均 O(1) 平均 O(1) 平均 O(1) O(n log n)​(提取键/值到数组排序)
二叉搜索树 节点 + 左右指针 平均 O(log n) 平均 O(log n) 平均 O(log n) 中序遍历 O(n)​(本身就是有序结构)
平衡树 节点 + 旋转/变色 O(log n) O(log n) O(log n) 中序遍历 O(n)​(本身有序)
数组(完全二叉树) O(1) 看最值 O(log n) O(log n) O(n log n)​(堆排序:建堆 O(n) + 逐个出堆 O(n log n))
B+ 树 多路节点 + 叶子链表 O(log_m n) O(log_m n) O(log_m n) 叶子遍历 O(n)​(叶子节点已有序串联)
Trie 多叉树 + 字符映射 O(k) O(k) O(k) O(总字符数)​(DFS 遍历收集即可有序输出)
跳表 多层有序链表 O(log n) O(log n) O(log n) O(n)​(本身有序,直接遍历即可)
邻接表(图)​ 数组 + 链表 O(degree) O(1) 加边 O(degree) 不适用(图无全局序概念)

排序列的关键解读

本身就有序的数据结构(排序时间就是遍历时间 O(n)):

  • 二叉搜索树 / 平衡树 / B+ 树:中序遍历即可得到有序序列,不需要额外排序操作
  • 跳表:底层链表已按 key 有序,从头到尾遍历就是排序结果
  • Trie:DFS 按字母序访问就能得到有序的字符串列表

需要额外排序算法的数据结构(排序时间 O(n log n)):

  • 数组 / 动态数组:可以直接应用快排、归并排序等,O(n log n) 是比较排序的极限
  • 链表:归并排序天然适合链表(不需要额外空间),时间复杂度 O(n log n)
  • 哈希表:元素无序,需提取所有键/值到数组后再排序
  • 栈 / 队列:同样需要先取出所有元素放入数组再排序

特别的排序方式

  • :堆排序本身就是基于堆的排序算法------建堆 O(n),然后逐个弹出堆顶元素 O(n log n),总计 O(n log n)。而且可以原地排序,不需要额外空间
  • B+ 树:叶子节点之间通过指针串联成链表,直接遍历叶子链即可得到有序结果,是数据库范围查询如此高效的原因

数组(Array)​

底层实现:​ 连续内存块,元素按索引顺序紧邻排列。每个元素占用固定大小的字节,通过 base_address + index * element_size 直接计算出地址。

操作 时间复杂度 原因
随机访问 O(1) 直接通过地址计算公式定位
搜索 O(n) 需遍历比较
末尾插入/删除 O(1) 直接操作最后一个位置
中间插入/删除 O(n) 需移动后续所有元素

有序数组的二分搜索可达 O(log n),但插入/删除仍需 O(n) 移动元素。


动态数组(ArrayList / Vector)​

底层实现:​ 底层仍然是连续数组,但额外维护容量和长度两个变量。当元素个数达到容量上限时,申请更大的新数组(通常为原容量的 1.5 倍或 2 倍),将旧数据逐一拷贝过去,再释放旧数组。

操作 时间复杂度 说明
随机访问 O(1) 同数组
末尾插入 摊还 O(1)​ 未满时直接写入 O(1);满时扩容拷贝 O(n),但扩容次数少,摊还下来为 O(1)
中间插入/删除 O(n) 需移动元素
搜索 O(n) 线性遍历

链表(Linked List)​

底层实现:​ 非连续存储,每个节点包含数据和指向下一节点的指针(单向链表)或前驱/后继指针(双向链表)。节点在内存中分散,通过指针串联。

类型 底层结构 查找 插入/删除(已知位置)
单向链表 节点 + next 指针 O(n) O(1)
双向链表 节点 + prev + next 指针 O(n) O(1)
循环链表 单向/双向 + 首尾相连 O(n) O(1)

关键特性:​ 链表不需要连续内存,插入/删除只需修改指针,因此是 O(1)。但随机访问必须从头遍历,没有下标计算,所以是 O(n)。


栈(Stack)与队列(Queue)​

底层实现:​ 既可以用数组实现(连续存储),也可以用链表实现。两种实现的时间复杂度一样。

数据结构 底层常用实现 入(push/enqueue) 出(pop/dequeue) 查看队首/栈顶
数组或链表 O(1) O(1) O(1)
队列 链表或循环数组 O(1) O(1) O(1)

队列的循环数组实现:维护头指针(front)和尾指针(rear),在数组逻辑上形成环,避免数组头部删除后大量移动元素。当数组满时同样需要扩容(摊还 O(1))。


哈希表(Hash Table)​

底层实现:​ 底层是数组(桶数组),通过哈希函数将键映射到数组下标。关键是解决哈希冲突的两种策略:

解决冲突方式 底层结构 平均查找 最坏查找 说明
拉链法 数组 + 链表/红黑树 O(1) O(n) / O(log n) Java 8+ 在链表长度 > 8 时转为红黑树优化
开放寻址法 纯数组(线性探测/二次探测) O(1) O(n) 需装载因子控制,如 Java ThreadLocalMap

装载因子(load factor)​ :当元素个数 / 桶数量超过阈值时触发扩容(rehash)​,重新分配更大的数组并将所有元素重新哈希,摊还成本为 O(1)。


树形结构

二叉搜索树(BST)​

底层实现:​ 节点结构(数据 + 左孩子指针 + 右孩子指针),递归定义:左子树所有节点 < 根节点 < 右子树所有节点。

操作 平均 最坏(退化为链表)
查找 O(log n) O(n)
插入 O(log n) O(n)
删除 O(log n) O(n)
平衡二叉搜索树(AVL / 红黑树)​

底层实现:​ 在 BST 节点基础上增加平衡因子 (AVL)或颜色标记 (红黑树),在插入/删除后通过旋转 (左旋/右旋)和变色恢复平衡。

特性 AVL 树 红黑树
平衡标准 左右子树高度差 ≤ 1 最长路径不超过最短路径的 2 倍
查找 O(log n) O(log n)
插入 O(log n) O(log n)
删除 O(log n) O(log n)
旋转次数(插入) 至多 1 次 至多 2 次
实际应用 适用于查询频繁的场景 适用于插入/删除频繁的场景(如 TreeMap、TreeSet)
B 树 / B+ 树

底层实现:​ 多路平衡搜索树,一个节点可以存储多个键值多个子节点指针。B+ 树的所有数据集中在叶子节点,叶子节点之间通过指针串联成有序链表。

操作 时间复杂度 应用场景
查找 O(log_m n) 数据库索引(InnoDB)、文件系统
插入 O(log_m n) 机械硬盘/SSD 友好(减少磁盘 I/O)
删除 O(log_m n) 范围查询效率极高(B+ 树)

m 为树的阶数,通常为几百到上千,因此树的高度很低(通常 3~4 层),磁盘 I/O 次数极少。

堆(Heap)​

底层实现:​ 通常用数组 实现(完全二叉树存储在数组中,下标 i 的左右孩子分别为 2i+1 和 2i+2)。堆化操作通过上浮(swim)​下沉(sink)​完成。

操作 时间复杂度 说明
查看最值 O(1) 堆顶即根节点,数组下标 0
插入 O(log n) 将元素放末尾,上浮调整
删除最值 O(log n) 将堆顶与末尾元素交换,下沉调整
建堆 O(n) Floyd 算法,从最后一个非叶子节点下沉

图(Graph)​

底层实现:​ 两种经典方式:

存储方式 底层结构 空间 查边 遍历所有邻边 适用场景
邻接矩阵 二维数组 V×V O(V²) O(1) O(V) 稠密图
邻接表 数组 + 链表/动态数组 O(V + E) O(degree) O(degree) 稀疏图

遍历时间复杂度:DFS 和 BFS 均为 O(V + E)(邻接表)或 O(V²)(邻接矩阵)。


Trie(前缀树 / 字典树)​

底层实现:​ 多叉树结构,每个节点包含一个字符映射表(数组或哈希表)和一个结束标记。根节点为空,路径上的字符拼接起来组成存储的字符串。

操作 时间复杂度 空间
插入 O(k) O(总字符数)
查找 O(k) ---
前缀搜索 O(k) ---

k 为字符串长度。Trie 的复杂度与数据量 n 无关,只与字符串长度相关,这是它相比哈希表做前缀查询时的核心优势。


跳表(Skip List)​

底层实现:​ 在有序链表的基础上,随机抽取部分节点建立多层索引。每一层都是下一层的一个"快速通道",从顶层开始逐层向下搜索。

操作 时间复杂度 空间
查找 平均 O(log n) O(n)
插入 平均 O(log n) ---
删除 平均 O(log n) ---

实际应用 :Redis 的 Sorted Set 底层使用了跳表加哈希表的组合。跳表实现简单,且支持范围查询(相较于哈希表)。

相关推荐
Yzzz-F24 分钟前
CF2023D
c++·算法·dp
_wxd66627 分钟前
排序-堆排序(Heap Sort)
数据结构
小小帅呀33 分钟前
学习 VLA 第6天:SWIN VIT算法原理以及复现
学习·算法
猎头南楼1 小时前
杭州算法工程师,偏大模型应用落地
算法
间歇性努力持续性发呆的野生快乐选手1 小时前
二分模板(整型,浮点型)
数据结构·c++·算法
evans在进步1 小时前
LeetCode 189 轮转数组:三次反转为什么能实现右旋?
数据结构·算法·leetcode
豆沙沙包?2 小时前
函数重载/类和对象(P14-P60)
前端·算法
lingchen19062 小时前
用MATLAB r2010b和r2016b求解微分方程组
开发语言·算法·matlab