树的相关知识整理2

原文(https://www.cnblogs.com/chengxiao/p/6129630.html)
堆排序:
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
堆的定义就是:
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

#include <iostream>
#include <vector>

using namespace std;

void adjust(vector<int> &arr, int len, int index){
    int left = 2*index+1;
    int right = 2*index+2;
    int maxIdx = index;
    if (left<len && arr[left]> arr[maxIdx]){
        maxIdx = left;
    }
    if (right< len && arr[right]> arr[maxIdx]){
        maxIdx = right;
    }
    if (maxIdx != index){
        swap(arr[maxIdx], arr[index]);
        adjust(arr, len, maxIdx);
    }

}
void heapSort(vector<int> &arr, int size){
    for (int i= size/2-1; i>=0;i--) {
        adjust(arr, size, i);
    }
    for (int i =size-1; i>=1; i--){
        swap(arr[0], arr[i]);
        adjust(arr, i, 0);
    }
}

int main(){


    vector<int > arr={2,3,5,6,6,59,5};
    heapSort(arr, arr.size());
    for (int i=0; i<arr.size();i++){
        cout<<arr[i]<<endl;
    }
    return 0;
}

二叉排序树(Binary Sort Tree),又称二叉查找树。

1、若左子树不为空,则左子树上所有结点的值均小于他的根结构的值;

2、若右子树不为空,则右子树上所有结点的值均大于他的根结构的值;

3、他的左、右子树也分别为二叉排序树。

使用中序遍历时,二叉排序树的输出顺序是由小到大的有序数列。
在按顺序向插入二叉搜索树中插入值,最后会形成一个类似链表形式的树,导致搜索效率下降
需要平衡,所以就设计出来了平衡二叉树,相对于二叉搜索树,平衡二叉树的一个特点就是,在该树中,任意一个节点,它的左右子树的差的绝对值一定小于2

(原博文:https://blog.csdn.net/lemon_tree12138/article/details/50393548?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1)
二叉树的插入与再平衡:
根据插入位置可以分为LL,RR,RL,LR:
在一个节点的左子树的左子树上插入一个新节点LL,右旋:
在这里插入图片描述
在一个节点的右子树的右子树上插入一个新节点。即RR,左旋
在这里插入图片描述
在一个节点的右子树的左子树上插入一个新节点。即RL,先让树中高度较低的进行一次右旋,这个时候就变成了RR了。再进行一次单左旋操作即可
先高度较低的树右旋,再进行一次左旋
在这里插入图片描述
(出处https://blog.csdn.net/qfc8930858/article/details/89856274)
红黑树相对于平衡二叉树的区别:
红黑树的性质:
1.节点是红色或黑色。
2.根节点是黑色。
3.每个叶子节点都是黑色的空节点(NIL节点)。
4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
5.从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
这些约束强制了红黑树的关键性质: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。

平衡二叉树的性质:

它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。这个方案很好的解决了二叉查找树退化成链表的问题,把插入,查找,删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间,不过相对二叉查找树来说,时间上稳定了很多。

区别:

1、红黑树放弃了追求完全平衡,追求大致平衡,在与平衡二叉树的时间复杂度相差不大的情况下,保证每次插入最多只需要三次旋转就能达到平衡,实现起来也更为简单。

2、平衡二叉树追求绝对平衡,条件比较苛刻,实现起来比较麻烦,每次插入新节点之后需要旋转的次数不能预知。

红黑树从根节点到每个叶子节点的路径都包含相同数量的黑色节点,因此从根节点到叶子节点的路径中包含的黑色节点数被称为树的“黑色高度(black-height)
(原文:)

一颗树黑色高度为3得红黑树,从根结点到叶结点的最短路径长度是3(黑-黑-黑),最长路径为4(黑-红-黑-红-黑)。由于第4条性质,不可能在最长路径中加入更多的黑色结点,因为性质3规定红色结点的子结点必须是黑色的,因此在同一简单路径中不允许有两个连续的红色结点。红黑树中最长路径就是一条红黑交替的路径
对于给定的黑色高度为n的红黑树,从根结点到叶结点的简单路径的最短长度为n-1,最大长度为2(n-1)。所有对树的操作必须保持上面列出的属性。特别要指出的是,插入和删除树的结点的操作必须遵循这些原则。

红黑树插入过程中情况
每次插入元素的时候会将 元素 着色为红色。其目的为了快的满足红黑树的4个条件

红黑树结构不会旋转变化情况:。
1)当插入的节点为的父亲为黑色节点。【什么都不用做】
2)被插入的节点是根节点。【直接把此节点涂为黑色】
红黑树结构发生旋转变化情况:
1) 当前节点的父节点【60】是红色,且当前节点的祖父节点【40】的另一个子节点(叔叔节点)也是红色。
2)当前插入的父节点是红色,当前叔叔节点的黑色,且当前节点为其父亲节点的左孩子。(进行左旋)
3)当前插入的父节点是红色,当前叔叔节点的黑色,且当前节点为其父亲节点的右孩子。(进行右旋)
如图 所示
在这里插入图片描述
红黑树结构发生旋转变化情况已经对应的措施如下
在这里插入图片描述
1.为什么会出现旋转?
对于平衡树来说,当插入或者删除的时候,树的结构会发生破坏因此会导致。因此需要对树进行旋转来保证树的平衡。

红黑树相关定理

1 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。

根据上面的性质5我们知道上图的红黑树每条路径上都是3个黑结点。因此最短路径长度为2(没有红结点的路径)。再根据性质4(两个红结点不能相连)和性质1,2(叶子和根必须是黑结点)。那么我们可以得出:一条具有3个黑结点的路径上最多只能有2个红结点(红黑间隔存在)。也就是说黑深度为2(根结点也是黑色)的红黑树最长路径为4,最短路径为2。从这一点我们可以看出红黑树是 大致平衡的。 (当然比平衡二叉树要差一些,AVL的平衡因子最多为1)

2 .红黑树的树高(h)不大于两倍的红黑树的黑深度(bd),即h<=2bd

根据定理1,我们不难说明这一点。bd是红黑树的最短路径长度。而可能的最长路径长度(树高的最大值)就是红黑相间的路径,等于2bd。因此h<=2bd。

3 一棵拥有n个内部结点(不包括叶子结点)的红黑树的树高h<=2log(n+1)
下面我们首先证明一颗有n个内部结点的红黑树满足n>=2bd-1。这可以用数学归纳法证明,施归纳于树高h。当h=0时,这相当于是一个叶结点,黑高度bd为0,而内部结点数量n为0,此时0>=20-1成立。假设树高h<=t时,n>=2^bd-1成立,我们记一颗树高 为t+1的红黑树的根结点的左子树的内部结点数量为nl,右子树的内部结点数量为nr,记这两颗子树的黑高度为bd’(注意这两颗子树的黑高度必然一 样),显然这两颗子树的树高<=t,于是有nl>=2bd’-1以及nr>=2bd’-1,将这两个不等式相加有nl+nr>=2(bd’+1)-2,将该不等式左右加1,得到n>=2(bd’+1)-1,很显然bd’+1>=bd,于是前面的不等式可以 变为n>=2bd-1,这样就证明了一颗有n个内部结点的红黑树满足n>=2bd-1。

    在根据定理2,h<=2bd。即n>=2^(h/2)-1,那么h<=2log(n+1)

    从这里我们能够看出,红黑树的查找长度最多不超过2log(n+1),因此其查找时间复杂度也是O(log N)级别的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值