当前位置: 首页 > news >正文

数据结构-树(二叉树、红黑、B、B+等)

​树的基本定义​

树的定义

树(Tree)​​ 是一种 ​​非线性数据结构​​,由 ​​节点(Node)​​ 和 ​​边(Edge)​​ 组成,满足以下条件:
​​有且仅有一个根节点(Root)​​:根节点没有父节点,是树的起点。
​​除根节点外,每个节点有且仅有一个父节点​​。
​​节点之间通过边连接​​,形成层次关系。
​​没有环路(Cycle)​​:从根到任意节点的路径唯一。

树的逻辑结构​

​​树形结构​​:
从根节点向下展开,形成多级分支,类似自然界中的树(倒置结构)。
节点间的连接具有 ​​方向性​​(父→子)和 ​​层次性​​。
​​递归定义​​:
一棵树由根节点和若干子树构成,每棵子树本身也是树。

核心术语​

在这里插入图片描述

树的分类​

根据节点子节点的限制,树可分为多种类型:
​​1.普通树​​:
每个节点可以有任意多个子节点。
2.​​二叉树(Binary Tree)​​:
每个节点最多有两个子节点(左子节点和右子节点)。
3.​​多叉树(N-ary Tree)​​:
每个节点最多有 N 个子节点(如 B 树、Trie 树)。

树的性质​

1.节点数​​:
一棵树有 n 个节点,则它有 n−1 条边(每条边对应一个父子关系)。
2.​​高度与节点数的关系​​:
对于高度为 h 的树,最少有 h+1 个节点(线性链状结构),最多有 2 h 2^h 2h−1 个节点(满二叉树)。

树的应用场景​

1.文件系统​​:
目录结构是树形层级(根目录→子目录→文件)。
2.​​数据库索引​​:
B+ 树用于加速数据查询。
3.​​组织架构​​:
公司部门层级关系(CEO→部门→团队→员工)。
​​4.算法与数据结构​​:
二叉搜索树、堆、哈夫曼树等用于高效操作。

树与其他数据结构的区别​

在这里插入图片描述

常见树结构

二叉树

​​定义​​:每个节点最多有两个子节点(左子节点和右子节点)。
​​特点​​:
结构简单,基础树形结构。
可用于构建其他复杂树结构(如二叉搜索树、堆)。
根节点(Root)​​:树的顶层节点,没有父节点。
​​叶子节点(Leaf)​​:没有子节点的节点。
​​内部节点(Internal Node)​​:至少有一个子节点的非叶子节点。

普通二叉树​

定义​​:每个节点最多有两个子节点,无其他约束。
​​示例​​:

      A/ \B   C/ \   \D   E   F

满二叉树(Full Binary Tree)​

​定义​​:所有非叶子节点都有两个子节点,且所有叶子节点在同一层。
特点​​:
深度为 h 的满二叉树有 2 h 2^h 2h−1 个节点。
​​示例​​:

      A/ \B   C/ \ / \D  E F  G

二叉搜索树(BST, Binary Search Tree)

定义​​:
左子树所有节点的值 < 根节点的值。
右子树所有节点的值 > 根节点的值。
​​特点​​:
中序遍历结果为有序序列。
如果平衡,查询效率高(O(logn))。
​​缺点​​:
可能退化为链表(插入顺序不佳时),查询效率降至 O(n)。
​​应用场景​​:
需要快速查找的有序数据集。

平衡二叉树(AVL 树、红黑树)

定义​​:
二叉搜索树的变种,通过旋转操作保持平衡。
任意节点的左右子树高度差不超过 1。
​​特点​​:
严格平衡,查询效率稳定(O(logn))。
​​缺点​​:
插入和删除时需要频繁旋转,维护成本高。
​​应用场景​​:
适合读多写少的场景(如字典)。
在这里插入图片描述

完全二叉树

​​定义​​:
除最后一层外,其他层节点数达到最大值。
最后一层的节点必须从左到右连续填充,中间不能有空缺。
​​示例​​:

      A/ \B   C/ \  /D  E F

二叉树的遍历​

        A/ \B   C/ \   \D   E   F
深度优先遍历(DFS)​

前序遍历(Preorder)​​:根 → 左 → 右

      ①A/   \②B    ⑤C/ \      \
③D ④E    ⑥F
结果​​:A → B → D → E → C → F

​​中序遍历(Inorder)​​:左 → 根 → 右

      ④A/   \②B    ⑥C/ \      \
①D ③E    ⑤F
​​结果​​:D → B → E → A → C → F

​​后序遍历(Postorder)​​:左 → 右 → 根

      ⑥A/   \③B    ⑤C/ \      \
①D ②E    ④F
​结果​​:D → E → B → F → C → A
广度优先遍历(BFS / 层次遍历)​

按层遍历​​:从根节点开始,逐层从左到右访问。

      ①A/   \②B    ③C/ \      \
④D ⑤E    ⑥F
结果​​:A → B → C → D → E → F

二叉树的应用​

1.​​二叉搜索树(BST)​​:快速查找、插入、删除有序数据。
​​2.堆(完全二叉树)​​:优先队列、堆排序。
​​3.哈夫曼树(Huffman Tree)​​:数据压缩(如 ZIP 文件)。
​​4.表达式树​​:解析数学表达式(如 (a + b) * c)。
​​5.决策树​​:机器学习分类模型。

红黑树(Red-Black Tree)

红黑树概述​​

红黑树(Red-Black Tree)​​ 是一种 ​​自平衡二叉搜索树​​,通过颜色标记和旋转操作维持树的平衡,确保最坏情况下的查找、插入和删除操作时间复杂度为 O(logn)。其核心设计目标是在插入和删除时减少平衡调整的次数,适合高频修改的数据场景。

红黑树的五大性质​

​​节点颜色​​:每个节点是红色或黑色。
​​根节点​​:根节点必须是黑色。
​​叶子节点​​:所有叶子节点(NIL节点,空节点)为黑色。
​​红色节点限制​​:红色节点的子节点必须为黑色(即不存在连续红色节点)。
​​黑高一致​​:从任一节点到其所有后代叶子节点的路径上,黑色节点的数量相同(称为 ​​黑高​​)。

红黑树的操作

插入操作​:

​​按BST规则插入新节点​​,并将其标记为红色。
​​修复红黑树性质​​:
​​Case 1​​:父节点为黑色 → 无需调整。
​​Case 2​​:父节点为红色,叔叔节点为红色 → 父节点和叔叔变黑,祖父变红,再递归处理祖父节点。
​​Case 3​​:父节点为红色,叔叔节点为黑色 → 通过旋转和重新着色调整(分左旋和右旋情况)。
示例​​(插入节点后修复):

插入前:B (祖父)/ \R () B (叔叔)/
R (新节点)修复后(Case 2):R (祖父)/ \B   B/R
删除操作​:

步骤​​:
​​按BST规则删除节点​​。
​​若删除节点为红色​​:直接删除,无需调整。
​​若删除节点为黑色​​:需通过旋转和颜色调整恢复黑高。
​​Case 1​​:兄弟节点为红色 → 旋转父节点,使兄弟变黑。
​​Case 2​​:兄弟节点为黑色,且兄弟的子节点均为黑 → 兄弟变红,递归处理父节点。
​​Case 3​​:兄弟节点为黑色,且兄弟的远侄子为红 → 旋转父节点并重新着色。
​​示例​​(删除黑色节点后的调整):

删除前:B ()/ \B (被删节点) R (兄弟)\B (远侄子)修复后(Case 3):B ()/ \B   B\R
旋转操作​​:

左旋(Left Rotate)​​:将右子节点提升为父节点,原父节点变为左子节点。

   P               R\             /R    →     P/             \L               L

右旋(Right Rotate)​​:将左子节点提升为父节点,原父节点变为右子节点。

     P           L/             \L       →       P\             /R           R

红黑树的应用​

​Java集合框架​​:TreeMap、TreeSet 基于红黑树实现。
​​C++ STL​​:map、multimap、set、multiset。
​​Linux内核​​:进程调度、内存管理等模块使用红黑树管理数据。
​​数据库系统​​:部分数据库的索引结构采用红黑树。

红黑树的性能分析​

时间复杂度​​:插入、删除、查找均为 O(logn)。
​​空间复杂度​​:O(n),每个节点存储颜色标记(1 bit)。
​​实际优化​​:通过减少旋转次数,红黑树在动态数据场景中表现优异。

B 树(B-Tree)​

B树(B-Tree)是一种​​多路平衡搜索树​​,广泛用于处理​​大规模数据存储​​(如数据库、文件系统)的场景。其核心设计目标是​​减少磁盘I/O次数​​,通过保持树的高度平衡,优化数据的存储与访问效率。
B树通过多路平衡的设计,在​​高并发、大规模数据存储​​场景中表现优异。理解其核心操作(分裂、合并)及平衡逻辑,是掌握数据库索引和文件系统优化的关键基础。对于需要频繁范围查询的场景,B+树通常是更好的选择。

B树定义

阶数(Order)​​:B树的阶数由正整数 M 表示,决定了每个节点的​​最大子节点数​​和​​关键字数量​​。
节点特性:
每个节点最多有 M 个子节点。
每个非根节点至少有 ⌈M/2⌉ 个子节点(根节点至少有2个子树,除非它是叶子节点)。
每个非根非叶子节点至少有 ⌈M/2⌉−1 个关键字,最多有 M−1 个关键字。
​​所有叶子节点位于同一层​​,保证树的高度平衡。

B树的核心性质​

​​1.平衡性​​:所有叶子节点在同一层,保证查找效率稳定。
​​2.多路分支​​:每个节点有多个子节点,减少树高。
3.​​自调整机制​​:插入操作可能触发​​节点分裂​​,删除操作可能触发​​节点合并​​或从兄弟节点借位,始终保持平衡。

B树的操作​

查找​​

类似二叉搜索树,但在每个节点内部通过二分法确定分支路径:
从根节点开始,按关键字有序遍历。
若找到匹配值,返回结果;否则进入对应区间子节点。
直到叶子节点结束。

插入​​

​​定位插入位置​​:找到对应的叶子节点。
​​插入关键字​​:
若叶子节点未满(关键字数 < M−1),直接插入。
若节点已满,进行​​分裂​​:
将中间关键字(中位数)提升到父节点。
分裂原节点为两个新节点,各包含一半关键字。
若父节点满,继续向上递归分裂。
​​分裂可能一直向上传播到根节点​​,导致树高增加。
​​示例​​:3阶B树插入关键字(每个节点最多2个关键字):
插入到满节点 [10,20] → 分裂为 [10] 和 [20],中间提升 10 到父节点。

删除

分两种情况处理:
​​删除叶子节点关键字​​:
直接删除,若关键字数不足下限,需从兄弟节点借位或合并节点。
​​删除内部节点关键字​​:
用前驱(左子树最大值)或后继(右子树最小值)替代被删节点,转为叶子节点删除。
​​合并操作​​:若节点关键字过少且兄弟节点无法借位,与父节点的分隔键合并。

B树的应用场景​​

​​数据库索引​​:B树支持高效的点查和范围查询,降低磁盘I/O。
​​文件系统​​:存储文件的元数据(如NTFS、Ext4)。
​​键值存储​​:如LevelDB的SSTable索引。

B树时间复杂度​​

查找、插入、删除的时间复杂度均为 ​​O( log ⁡ m n \log_{m}n logmn)​​,其中 M 为阶数,N 为数据总量。
由于 M 通常较大,树高远低于二叉树(如 log ⁡ 100 n \log_{100}n log100n vs log ⁡ 2 n \log_{2}n log2n),显著减少磁盘访问次数。

B+ 树(B+ Tree)​

B+树(B-Plus Tree)是B树的变种,专为​​大规模数据存储​​和​​高效范围查询​​设计。它在数据库索引、文件系统等领域应用广泛,核心特点是​​数据仅存储在叶子节点​​,并通过叶子节点的​​链表连接​​优化顺序访问。

B+树的定义

​​阶数(Order)​​:由正整数 M 表示,决定每个节点的​​最大子节点数​​和​​关键字数量​​。
​​节点特性​​:
​​内部节点​​(非叶子节点):
存储关键字作为​​索引​​(分隔键),不存储实际数据。
最多有 M 个子节点,至少有 ⌈M/2⌉ 个子节点(根节点例外)。
​​叶子节点​​:
存储​​所有关键字和对应的数据指针​​(或数据本身)。
叶子节点通过​​双向链表​​连接,支持高效顺序遍历。
每个叶子节点至少有 ⌈M/2⌉ 个关键字,最多有 M−1 个关键字。
​​所有叶子节点位于同一层​​,保证树高平衡。

B+树的核心性质​

数据分离​​:内部节点仅存索引,数据全在叶子节点。
​​顺序访问优化​​:叶子节点通过链表连接,支持高效范围查询。
​​更高的分支因子​​:因内部节点不存数据,可容纳更多关键字,进一步降低树高。

B+树的操作​​

查找​​

​​点查​​:
从根节点开始,按关键字比较向下遍历。
最终到达叶子节点,若存在匹配关键字,返回数据;否则返回空。
​​范围查询​​:
找到起始关键字所在的叶子节点。
沿链表顺序遍历,直到终止关键字。

​​插入​​

​​定位插入位置​​:找到对应的叶子节点。
​​插入关键字​​:
若叶子节点未满(关键字数 < M−1),直接插入。
若叶子节点已满,进行​​分裂​​:
将中间关键字(中位数)​​复制到父节点​​作为索引。
分裂原节点为两个新节点,各包含一半关键字。
若父节点已满,递归向上分裂。
​​分裂规则​​:与B树不同,中间关键字在父节点中被复制而非移动。
​​示例​​:3阶B+树插入关键字(每个节点最多2个关键字):
插入到满叶子节点 [10,20] → 分裂为 [10] 和 [20],中间关键字 20 被复制到父节点作为索引。

删除​​

​​定位删除位置​​:找到目标关键字所在的叶子节点。
​​删除关键字​​:
若叶子节点关键字数仍满足下限(≥ ⌈M/2⌉),直接删除。
若关键字数不足,尝试从兄弟节点借位:
若兄弟节点有富余关键字,调整父节点索引。
若无法借位,与兄弟节点合并,并删除父节点中的冗余索引。
​​合并传播​​:合并可能导致父节点关键字不足,递归向上调整。

B+树的应用场景​​

​​数据库索引​​(如MySQL InnoDB):
范围查询(BETWEEN、ORDER BY)高效。
全表扫描只需遍历叶子链表。
​​文件系统​​(如ReiserFS、XFS):
快速定位文件块。
​​键值存储引擎​​(如RocksDB、MongoDB默认存储引擎WiredTiger)。

B+树的时间复杂度​

查找、插入、删除的时间复杂度均为 ​​O( log ⁡ m n \log_{m}n logmn​​)
由于内部节点不存储数据,分支因子 M 更大,树高更低,I/O次数更少。

B+树 vs B树​

在这里插入图片描述

Trie 树(字典树)​

Trie 树(​​字典树​​或​​前缀树​​)是一种专门用于​​字符串检索​​和​​前缀匹配​​的树形数据结构。其核心思想是通过字符串的公共前缀来共享存储空间,优化查询效率,广泛应用于​​搜索引擎​​、​​输入法提示​​、​​路由表​​等场景。

Trie 树的定义​

节点结构​​:每个节点代表一个字符,从根节点到某一节点的路径构成一个字符串。
​​根节点​​:不存储字符,表示空字符串。
​​子节点​​:每个节点的子节点对应不同字符(如26个小写字母、ASCII字符等)。
​​结束标记​​:节点可附加标记(如 is_end)表示是否为一个完整字符串的结尾。
​​示例​​:插入字符串 [“apple”, “app”, “banana”] 的 Trie 树结构:
root
/
a b
/
p a
/
p (is_end) n
/
p a
/ \
l (is_end) n
\
e (is_end) a (is_end)

Trie 树的核心性质​

​​前缀共享​​:具有相同前缀的字符串共享路径,减少冗余存储。
​​快速检索​​:查找时间复杂度与字符串长度相关,​​与数据量无关​​。
​​自动排序​​:按字典序插入时,Trie 树天然支持有序遍历。

Trie 树的操作​

插入字符串​​

从根节点开始,逐字符遍历字符串。
若字符对应的子节点不存在,则创建新节点。
到达字符串末尾时,标记当前节点为结束节点(is_end = true)。
​​示例​​:插入 “apple”:
root → a → p → p → l → e(标记 e 节点为结束)。

查找字符串​​

从根节点开始,逐字符向下匹配。
若路径中途子节点不存在,返回 false。
若到达字符串末尾且当前节点标记为结束,返回 true。
​​示例​​:查找 “app”:
root → a → p → p(该节点标记为结束,存在)。

查找前缀​​

与查找字符串类似,但无需检查结束标记,只需确认前缀存在。

​​删除字符串​​

先查找字符串是否存在。
若存在,从叶子节点向上回溯删除节点,直到遇到有其他子节点或标记为结束的节点。
​​注意​​:需处理共享前缀的情况,避免误删其他字符串。

Trie 树的应用场景​

搜索引擎自动补全​​:根据输入前缀快速推荐候选词。
​​拼写检查​​:快速判断单词是否存在。
​​路由表匹配​​:IP地址前缀匹配(需结合压缩优化)。
​​词频统计​​:在节点中存储计数信息。
​​敏感词过滤​​:结合AC自动机(Aho-Corasick)实现多模式匹配。

Trie 树时间复杂度​

​​插入​​:O(L),其中 L 为字符串长度。
​​查找​​:O(L)。
​​前缀匹配​​:O(L)。

堆(Heap)​

堆(Heap)是一种基于​​完全二叉树​​的抽象数据结构,具有独特的​​堆序性​​,常用于高效获取数据集中的​​最大值​​或​​最小值​​。堆分为​​最大堆​​和​​最小堆​​,分别用于快速访问极值,是优先队列(Priority Queue)的底层实现核心。

堆的定义​

​​完全二叉树​​:除最后一层外,其他层节点全满,最后一层节点从左到右填充。
​​堆序性​​:
​​最大堆​​:父节点的值 ≥ 子节点的值(根节点为最大值)。
​​最小堆​​:父节点的值 ≤ 子节点的值(根节点为最小值)。
​​存储结构​​:通常用​​数组​​实现,利用完全二叉树的性质简化索引计算。

堆的核心性质​

1.​​结构特性​​:
完全二叉树,高度为 O(logn)。
数组表示中,节点索引关系:
父节点索引:parent(i)=⌊(i−1)/2⌋
左子节点索引:left(i)=2i+1
右子节点索引:right(i)=2i+2
2.​​堆序性​​:仅保证父节点与子节点的大小关系,不保证兄弟节点有序。

堆的操作​

插入元素(Insert)​​

​​添加到末尾​​:将新元素插入数组末尾。
​​上浮(Percolate Up)​​:从新元素开始,与父节点比较并交换,直到满足堆序性。
​​示例​​:在最大堆 [70, 60, 50, 20, 10] 中插入 65:
插入后数组 → [70, 60, 50, 20, 10, 65]
上浮过程:65 > 20 → 交换 → 65 > 60 → 交换 → 最终堆 → [70, 65, 50, 60, 10, 20]

删除堆顶元素(Extract-Max/Min)​​

​​交换堆顶与末尾​​:将堆顶元素与最后一个元素交换,删除末尾。
​​下沉(Percolate Down)​​:从堆顶开始,与较大(或较小)的子节点交换,直到恢复堆序性。
​​示例​​:从最大堆 [70, 65, 50, 60, 10, 20] 删除堆顶:
删除后数组 → [20, 65, 50, 60, 10]
下沉过程:20 < 65 和 50 → 与 65 交换 → 20 < 60 → 交换 → 最终堆 → [65, 60, 50, 20, 10]

​​构建堆(Heapify)​​

​​Floyd算法​​:从最后一个非叶子节点开始,逐个节点执行下沉操作。
​​时间复杂度​​:O(n),数学证明基于树高和节点数量关系。

堆的应用场景​

堆排序​​:通过构建堆,依次取出堆顶元素实现排序(时间复杂度 O(nlogn))。
​​优先队列​​:任务调度、事件驱动模拟(如Dijkstra算法)。
​​Top K 问题​​:快速找到数据流中最大的K个元素。
​​合并有序序列​​:K路归并时,用堆高效选择最小元素。

堆时间复杂度​

在这里插入图片描述

各种树对比

在这里插入图片描述

相关文章:

  • Sentry 异常捕获
  • 【数据分享】2020年中国高精度森林覆盖数据集(免费获取)
  • QMK机械键盘固件开发指南:从源码到实践
  • ffmpeg 元数据
  • Python 常用内置函数详解(七):dir()函数——获取当前本地作用域中的名称列表或对象的有效属性列表
  • stm32数码管显示数字/循环
  • 【Redis】Another Redis Desktop Manager 安装指南
  • podman/docker国内可用的docker镜像源(2025-05)
  • Linux btop 使用教程
  • Wireshark抓取SMTP协议报文
  • 如何提升自我执行力?
  • Linux51 安装baidunetdisk yum install rpm -ivh
  • 中科院:通过内部表示优化LLM上下文利用
  • 图解 Git 工作流:理解 Rebase、Merge 与 Pull Request 的区别
  • 21 课时精通生成式 AI:微软官方入门指南详解
  • 【设计模式】GoF设计模式之备忘录模式(Memento Pattern)
  • LTspice
  • 【软件设计师:复习】上午题核心知识点总结(二)
  • 大模型蒸馏技术
  • 【业务领域】电脑主板芯片电路结构
  • “五一”假期首日:国铁南宁局发送旅客81.7万人次
  • 申活观察|咖香涌动北外滩,带来哪些消费新想象?
  • 停电催生商机,中国品牌 “照亮” 西班牙
  • 经济日报社论:书写新征程上奋斗华章
  • 马上评|什么才是地方文旅宣传的正确姿势
  • 专访|200余起诉讼,特朗普上台100天,美国已进入宪政危机