本页详细介绍了树和图数据结构、它们的各种实现以及时间复杂度。这些数据结构是计算机科学的基础,并在技术面试中占有重要地位。有关使用这些结构实现的算法,请参阅算法参考和图算法。
树是一种无向、连通、无环的图。在计算机科学中,树是一种分层数据结构,由通过边连接的节点组成,具有单个根节点且无循环。
来源: README.md95-104
二叉树是一种树数据结构,其中每个节点最多有两个子节点,分别称为左子节点和右子节点。
来源: README.md98-104
二叉搜索树(Binary Search Tree,简称 BST)是一种特殊的二叉树,它保持以下特性:
这种排序特性使得搜索、插入和删除操作效率很高。
O(log(n)),最坏情况下为O(n)O(log(n)),最坏情况下为O(n)O(log(n)),最坏情况下为O(n)O(log(n)),最坏情况下为O(n)该仓库包含了各种 BST 实现和操作,例如:
来源: README.md106-115
Trie,有时称为基数树或前缀树,是一种用于存储动态集或关联数组的搜索树,其中键通常是字符串。节点在树中的位置定义了它所关联的键。一个节点的所有后代都与该节点关联着一个共同的前缀,而根节点则与空字符串关联。
Trie 在以下方面特别有用:
该仓库在 Trie/implementTrie.java 中实现了 Trie,并将其用于解决诸如单词搜索设计 Trie/addAndSearchWordDataStructureDesign.java 和单词方块 Trie/wordSquares.java 等问题。
来源: README.md118-124
Fenwick 树是一种数据结构,可以高效地更新数组中的元素和计算前缀和。虽然被称为树,但它通常使用数组实现。节点父或子的索引是通过对其索引的二进制表示进行位运算来计算的。
时间复杂度
O(log(n))O(log(n))来源: README.md126-136
线段树是一种用于存储区间或线段的树数据结构。它允许查询哪些线段包含给定点。它对范围查询问题特别有用。
时间复杂度
O(log(n))O(log(n))来源: README.md138-145
树的遍历是访问树中每个节点的基本操作。主要的遍历方法有:
深度优先遍历:
广度优先遍历:
该仓库包含了各种树的遍历和操作的实现:
来源: README.md417-422 README.md424-431
图是一个有序对 G = (V, E),由一组顶点或节点 V 和一组边或弧 E 组成,其中边是 V 的2元素子集。换句话说,图是由边连接的节点集合。
无向图(Undirected Graph):边没有方向的图。如果存在从节点 u 到节点 v 的边 (u → v),那么也存在从节点 v 到节点 u 的边 (v → u)。
有向图(Directed Graph / Digraph):边有方向的图。如果存在从节点 u 到节点 v 的边 (u → v),这并不意味着存在从节点 v 到节点 u 的边 (v → u)。
加权图(Weighted Graph):每条边都有相关联的权重(成本)的图。
连通图(Connected Graph):任意一对顶点之间都有路径的图。
循环图(Cyclic Graph):包含至少一个循环(起点和终点相同的路径)的图。
来源: README.md175-186
表示图的两种常用方式
一个 V×V 的二维数组,其中 V 是顶点数量。如果从顶点 i 到顶点 j 存在边,则 adjacency[i][j] = 1,否则 adjacency[i][j] = 0。
优点:
缺点:
一个列表数组,其中每个列表描述图中一个顶点的邻居集合。
优点:
缺点:
来源: README.md175-186
DFS 是一种图遍历算法,它在回溯之前尽可能深地探索每个分支。它使用栈(通常通过递归实现)来跟踪要探索的节点。
时间复杂度: O(|V| + |E|),其中 |V| 是顶点数,|E| 是边数。
应用程序:
该仓库包含了用于解决以下问题的 DFS 实现:
来源: README.md230-236 README.md424-431
BFS 是一种图遍历算法,它在进入下一深度层级的节点之前,探索当前深度层级的所有邻近节点。它使用队列来跟踪要探索的节点。
时间复杂度: O(|V| + |E|)
应用程序:
该仓库包含了用于解决以下问题的 BFS 实现:
来源: README.md238-242 README.md417-423
拓扑排序是一种用于对有向无环图(DAG)的顶点进行排序的算法,使得对于每条有向边 (u, v),顶点 u 在排序中都出现在顶点 v 之前。
时间复杂度: O(|V| + |E|)
应用程序:
来源: README.md244-249
这些算法用于查找图中节点之间的最短路径。
在具有非负权重的加权图中,查找从单个源点到所有其他顶点的最短路径。
时间复杂度: 邻接矩阵为 O(|V|²),带最小堆为 O(|E| + |V|log|V|)
来源: README.md250-254
计算加权图中从单个源点出发的最短路径。与 Dijkstra 算法不同,它可以处理带有负权重边的图。
时间复杂度:
来源: README.md256-265
在加权图中查找所有顶点对之间的最短路径,该图可以有正边或负边权重(但不能有负循环)。
时间复杂度: O(|V|³)
来源: README.md266-274
这些算法找到边的子集,这些边形成一棵包含每个顶点的树,并且树中所有边的总权重最小。
一种贪婪算法,用于查找加权无向图的最小生成树。
时间复杂度: 邻接矩阵为 O(|V|²),带二叉堆为 O(|E|log|V|)
来源: README.md275-280
另一种用于查找图的最小生成树的贪婪算法。与 Prim 算法不同,它不需要图最初是连通的。
时间复杂度:O(|E|log|V|)
来源: README.md282-286
数独有效性问题可以看作是一个图着色问题,其中每个单元格都是一个顶点,约束是边。该仓库中包含的实现包括:
该解决方案使用 HashSets 来检查数字是否已存在于行、列或 3x3 方块中,从而有效地验证了数独谜题的约束。
来源: company/apple/ValidSudoku.java9-29 company/snapchat/ValidSudoku.java9-29 company/uber/ValidSudoku.java9-29 leetcode/hash-table/ValidSudoku.java9-29
下图展示了仓库中不同树和图概念的实现方式
来源: README.md499-506 README.md507-510 README.md416-423 README.md424-431
| 数据结构 / 算法 | 访问 | 搜索 | 插入 | 删除 | 附加操作 |
|---|---|---|---|---|---|
| 二叉搜索树 | O(log n)* | O(log n)* | O(log n)* | O(log n)* | * 假定为平衡树 |
| Trie树 | O(m)** | O(m)** | O(m)** | O(m)** | ** m 为键长 |
| Fenwick 树 | - | - | O(log n) | - | 范围求和: O(log n) |
| 线段树 | - | - | O(log n) | - | 范围查询: O(log n) |
| DFS / BFS | - | O(V+E) | - | - | - |
| Dijkstra 算法 | - | - | - | - | 最短路径: O(V²) |
| Bellman-Ford | - | - | - | - | 最短路径: O(VE) |
| Floyd-Warshall | - | - | - | - | 所有对最短路径: O(V³) |
| 普里姆算法 | - | - | - | - | MST: O(V²) |
| 克鲁斯卡尔算法 | - | - | - | - | MST: O(E log V) |
来源: README.md106-145 README.md230-286
树和图是计算机科学中具有广泛应用的基础数据结构。理解它们的属性、操作和算法对于技术面试和软件开发至关重要。该仓库提供了各种树和图问题的实现,以实践这些概念。
刷新此 Wiki
最后索引时间2025 年 4 月 18 日(a70c22)