专栏原创出处:github-源笔记文件 ,github-源码 ,欢迎 Star,转载请附上原文出处链接和本声明。
文章目录
1. 树的概念
具有 n ( n ≥ 0 ) n(n\ge 0) n(n≥0) 个节点的有限集称为树。
当 n = 0 n = 0 n=0 时称为空树;
当 n ≥ 1 n\ge 1 n≥1 时,仅有一个特定的称为根的结点,其余结点可分为 m ( m ≥ 0 ) m(m\ge 0) m(m≥0) 个互不相交的有限集。每一个集合本身又是一棵树,称为根的子树。
特点:树是非线性结构,数据元素具有"一对多"的逻辑关系;树中的每个元素最多有一个前驱结点,有多个后继结点。
树结构中的常见用语:
- 节点的深度 - 从树的根节点到该节点的边数
- 节点的高度 - 该节点和叶子之间最长路径上的边数
- 树的高度 - 其根节点的高度
2. 二叉树
二叉树是一种更为典型的树树状结构。如它名字所描述的那样,二叉树是每个节点最多有两个子树的树结构,通常子树被称作“左子树”和“右子树”。
2.1 二叉树的遍历
- 前序遍历:首先访问根节点,然后遍历左子树,最后遍历右子树。
- 中序遍历:先遍历左子树,然后访问根节点,然后遍历右子树。
- 后序遍历:先遍历左子树,然后遍历右子树,最后访问树的根节点。
- 层级遍历:逐层遍历,二叉树的最大深度也就是层级树。
对于上述三种遍历,我们简化为,前中后只是表明遍历时「根节点的位置」,不管根在哪儿都是从左向右。每次遍历到节点时把它看做时一棵新树按刚刚的方式继续遍历。
我们可以简化为一个不需要记忆的方法:
- 前序遍历:根 左 右
- 中序遍历:左 根 右
- 后序遍历:左 右 根
1. 二叉树的关系:
- 中序遍历不能唯一确定一棵二叉搜索树;
- 先序和后序遍历不能唯一确定一棵二叉搜索树;
- 中序后序可以唯一确定一棵二叉树;
- 中序先序可以唯一确定一棵二叉树。
- 根据「中序后序」「中序先序」构造二叉树步骤:
- 通常从先序序列或者后序序列开始,根据不同遍历方法的规律,选择合适的节点构造树;
- 例如:先序序列的第一个节点是根节点,然后是它的左孩子,右孩子等等。后序序列的最后一个节点是根节点,然后是它的右孩子,左孩子等等;
- 从先序/后序序列中找到根节点,根据根节点将中序序列分为左子树和右子树;
- 从中序序列中获得的信息是:如果当前子树为空(返回 None),否则继续构造子树。
3. 常见算法题:
前序遍历、中序遍历、后序遍历、层级遍历、计算二叉树的最大深度。
从前序与中序遍历序列构造二叉树、从中序与后序遍历序列构造二叉树、二叉树的最近公共祖先
2.2 二叉树的类型
完美二叉树:又叫满二叉树,除叶子节点所有子节点都有左右子节点。
完全二叉树:除叶子节点所有子节点都有左右子节点。
2.3 二叉树相关算法
推荐 力扣-卡片-二叉树
3. 二叉查找树
二叉查找树(BST)是二叉树的一种特殊表示形式(也叫二叉查找树),它满足如下特性:
- 每个节点中的值必须大于等于存储在其左子树中的任何值。
- 每个节点中的值必须小于等于存储在其右子树中的任何值。
像普通的二叉树一样,我们可以按照前序、中序和后序来遍历一个二叉查找树。但是,对于二叉查找树,我们可以通过中序遍历得到一个「递增的有序序列」。因此,中序遍历是二叉查找树中最常用的遍历方法。
上述图中是一个二叉查找树,中序遍历结果为 1 2 4 6 8 10 ... 30 32 34 36
3.1 二叉查找树操作
搜索操作:
- 如果目标值等于节点的值,则返回节点;
- 如果目标值小于节点的值,则继续在左子树中搜索;
- 如果目标值大于节点的值,则继续在右子树中搜索。
插入操作:
与搜索操作类似,对于每个节点,我们将:
- 根据节点值与目标节点值的关系,搜索左子树或右子树;
- 重复步骤 1 直到到达外部节点;
- 根据节点的值与目标节点的值的关系,将新节点添加为其左侧或右侧的子节点。
删除操作:
- 如果目标节点没有子节点,我们可以直接移除该目标节点。
- 如果目标节只有一个子节点,我们可以用其子节点作为替换。
- 如果目标节点有两个子节点,我们需要用其中序后继节点或者前驱节点来替换,再删除该目标节点。
3.2 二叉查找树相关算法
4. 平衡二叉查找树
平衡二叉查找树:是一种结构平衡的二叉查找树,即叶节点高度差的绝对值不超过 1,并且左右两个子树都是一棵平衡二叉树。
从上图可以分析如果我们计算一颗树是否是高度平衡时,自上而下的计算会重复计算子节点,如果我们自下而上计算并比较当前节点高度可以避免该问题。
有 N 个节点的平衡二叉查找树,它的高度是 l o g N logN logN。
为什么是 l o g N logN logN 呢?
- 一个高度为 h 的二叉树: 2 0 + 2 1 + ⋯ + 2 h = 2 h + 1 − 1 2^0+2^1+\cdots+2^h = 2^{h+1} -1 20+21+⋯+2h=2h+1−1
- 一个有 N 个节点,且高度为 h 的二叉树: N ≤ 2 h + 1 − 1 N \leq 2^{h+1} -1 N≤2h+1−1
- 所以: h ≥ ∣ log 2 N ∣ h\geq|\log_2{N}| h≥∣log2N∣
4.1 为什么需要用到平衡二叉查找树?
以搜索操作为例,如果二叉查找树的高度为 h,则时间复杂度为 O(h)。二叉查找树的高度的确很重要。
通过上文可知
h
≥
∣
log
2
N
∣
h\geq|\log_2{N}|
h≥∣log2N∣,所以具有
N
N
N个节点的二叉查找树的高度在
log
N
\log{N}
logN 到
N
N
N 区间变化。也就是说,搜索操作的时间复杂度可以从
log
N
\log{N}
logN 变化到
N
N
N。这是一个巨大的性能差异。
所以说,高度平衡的二叉查找树对提高性能起着重要作用。
常见的平衡二叉查找树有:
4.2 实际应用
平衡二叉查找树的概念经常运用在 Set、Map 中。
比如 Java 语言中:
TreeSet 底层使用 TreeMap 实现,而 TreeMap 底层使用红黑树实现。HashSet 底层使用 HashMap 实现,而 HashMap 底层实现了链表+红黑树实现。
参考
更多相关专栏内容汇总: