目录
一、红黑树
1.1 定义
1.2 性质
1.3 基本操作
左旋
右旋
变色
1.4 操作
查找
插入
直接插入
插入后需要变形与递归
1.5 一个插入实例
二、二叉搜索树
2.1 定义与性质
2.2 判断二叉搜索树
三、两道编程题及思路
3.1 是排序二叉树
3.2 带有指向父节点的指针
3.3 没有父指针
https://baike.baidu.com/item/%E7%BA%A2%E9%BB%91%E6%A0%91/2413209?fr=aladdin
红黑树(Red Black Tree) 是一种自平衡二叉查找树,典型的用途是实现关联数组。它虽然是复杂的,但它的最坏情况运行时间也是非常良好的,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。
https://www.jianshu.com/p/e136ec79235c
一层红,一层黑。也叫二叉查找树
红黑树并不是一个完美平衡二叉查找树,例如上面,左子树比右子树高2,但是根据性质5,性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。所以我们叫红黑树这种平衡为黑色完美平衡。
排序二叉树左旋或者右旋操作之后,依然是排序二叉树?是的。
左旋只影响旋转结点和其右子树的结构,把右子树的结点往左子树挪了。
右旋只影响旋转结点和其左子树的结构,把左子树的结点往右子树挪了。
结点的颜色由红变黑或由黑变红。
因为红黑树是一颗二叉平衡树,并且查找不会破坏树的平衡,所以查找跟二叉平衡树的查找无异:
两步。1.查找插入位置。2.插入后的自平衡。
直接插入的情况:
存在下面两种基本情况,此后的情况可根据下面两种进行变形。
1. 插入节点父节点的父节点为红色,叔节点存在且为红色:
红黑树自底向上进行生长,所以插入节点为红,自底向上到祖父节点依次进行变色。(最复杂的情况,增加了路径中黑色节点的数目)
此时,相当于插入了祖父节点PP,往下递归。
2. 插入节点叔节点不存在:插入,自底向上父节点、祖父节点进行旋转操作(即可完成平衡,相对简单)。
详见:
https://www.jianshu.com/p/e136ec79235c
步骤1:需要插入21,相当于红色子节点的左子树。(叔节点存在且为红色)
步骤2:变色,插入之后,不能满足红色节点不能相邻,所以插入节点的父节点与祖父节点变色。
步骤3:变色后相当于在祖父位置插入节点25,节点25的叔节点存在且红节点,需要向上变色。
步骤4:变色后,根节点为红色,需要左旋转操作把根节点换位黑色。
步骤5, 因为不满足一层红色一层黑色,向下递归一个节点右旋。
https://blog.csdn.net/hh66__66hh/article/details/82947113
二叉查找树(Binary Search Tree),也叫二叉排序树。
最小值与最大值
查找最小值:因为二叉搜索树中,左节点比父节点小,故最小值肯定在树的左下角。从根节点开始,判断它的左节点存不存在。如果存在,继续找这个左节点的左节点,如此类推,直到找到某个节点的左节点不存在时,此节点就是最小值。
查找最大值:因为二叉搜索树中,右节点比父节点大,故最大值肯定在树的右下角。从根节点开始,判断它的右节点存不存在。如果存在,继续找这个右节点的右节点,如此类推,直到找到某个节点的右节点不存在时,此节点就是最大值。
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。
class Solution {
public:
bool VerifySquenceOfBST(vector sequence) {
int vector_size = sequence.size();
if (vector_size < 1)return false;
int root = sequence[vector_size - 1];
int location = 0;
vector left_sequence, right_sequence;
while (sequence[location] < root){
left_sequence.push_back(sequence[location]);
location++;
}
while ((sequence[location] > root)){
right_sequence.push_back(sequence[location]);
location++;
}
if (location < vector_size - 1)
return false;
else{
bool left = true;
if (left_sequence.size()>1)left = VerifySquenceOfBST(left_sequence);
bool right = true;
if (right_sequence.size()>1)right = VerifySquenceOfBST(right_sequence);
return left&&right;
}
}
};
剑指offer后面P345
题干:已经知道两个节点,如何求他们的公共祖先?
从根向下遍历,如果值介于两个节点值之间,则这个结点必然是两个值的公共祖先。
则相当于判断两个链表的第一个公共节点的问题。
如果没有父指针:
找到根节点到通过的节点回归一个链表,然后找到两个链表的公共节点。
这个问题就转换成了两个问题: