首页 > 其他分享 >lec4.1-Specific Trees(AVL Tree; B Tree)

lec4.1-Specific Trees(AVL Tree; B Tree)

时间:2024-12-23 19:32:28浏览次数:10  
标签:lec4.1 right null Tree element Specific else 节点 left

lec4-Specific Trees

1. binary search trees 二叉搜索树

1.1. 二叉搜索树的定义

  • 对于任意一个节点,左子树上的所有 element 都小于根节点的 element,右子树节点都大于
  • element 相同的节点是不存在的
  • 这样来看,中序遍历就是有顺序的遍历

1.2. (indexed BST)带索引的二叉搜索树

int leftSize; // 左子树的节点数加一
  • 这是添加的关键成员变量
  • 想想怎么用递归方法找到 kth 的数字(左子树的所有节点就是所有小于根的节点)

1.3. BST的增删查

1.3.1. find
private BinaryNode find(Comparable x, BinaryNode t){
    if(t == null) return null;
    if(x.compareTo(t.element) < 0)
        return find(x, t.left);
    if(x.compareTo(t.element) > 0)
        return find(x, t.right);
    else // x == t.element
    	return t; 
}
  • 这里就是简单的递归思想,也是BST几乎所有算法都会用到的套路
BinaryNode findMin() // 可以递归做,也可以循环做
BinaryNode findMax()
1.3.2. insert
private BinaryNode insert(Comparable x, BinaryNode t){
    if(t == null) return new BinaryNode(x, null, null);
    else if(x.compareTo(t.element) < 0){
        t.left = insert(x, t.left); //这里就是认为左子树做好了处理,可以直接使用t.left
    }else if(x.compareTo(t.element) > 0){
        t.right = insert(x, t.right);
    }else ;// 这里表示已经重复,可以报错等等,不需要处理
    return t; // 已经做好处理了,就可以返回了
}
1.3.3. remove
  • 这里要分三种情况进行讨论
    • 删除叶子节点
      直接删除
    • 删除有一条分支节点
      直接删除,但是要连接好上下
    • 删除有两条分支节点
      先取出前驱或者后继来取代这个节点,然后在对应的子树上删除前驱或者后继
      也就是要(findMin(),findMax())
private BinaryNode remove(Comparable x, BinaryNode t){
    if(t == null) return t;
    else if(x.compareTo(t.element) < 0)
        t.left = remove(x, t.left);
    else if(x.compareTo(t.element) > 0)
        t.right = remove(x, t.right);
    else{ // 只有找到了这个节点,才可以进入下一步三种情况的讨论!!!
        if(t.left != null && t.right != null){ // 第一种情况,两个分支
            t.element = findMin(t.right).element; //找出后继
            t.right = remove(t.element, t.right);
        }else if(t.left != null){
            t = t.left;
        }else if(t.right != null){
            t = t.right;
        }else{ // 直接删掉
            t = null;
        }
    }
    return t;
}

查询,插入,删除需要的时间复杂度都是 O(h),为了增加层数,我们有了AVL树

2. AVL Tree(平衡二叉搜索树)

2.1. AVL树的定义

  • AVL树是一棵二叉搜索树
  • 每一个节点都满足: 左右子树高度差不超过1
    • 可以维护树高或者是 balance 来看
  • 可以证明,树高与节点数成对数关系

2.2. AVL树的增删查

2.2.1. 查询
  • 查询与BST完全一致
2.2.2. 插入
  • 左外侧太高的时候:
    对根节点,右旋转
  • 左内侧太高的时候:
    对根节点,先左旋转(这样就变成了左外侧的情况),后右旋转
private AVLNode insert(Comparable x, AVLNode t){
    if(t == null)
        t = new AVLNode(x, null, null);
    else if(x.compareTo(t.element) < 0){
        t.left = insert(x, t.left); // 注意!这里表示的是,左侧已经成功插入了平衡的子树
        if(height(t.left) - height(t.right) == 2){
            if(x.compareTo(t.left.element) < 0){ // 我想要插入的数字,成功插到了左子树的外侧?内侧?
                t =  rotateWithLeftChild(t); // 注意:这里的意思是,左外侧要做的操作,实际上也是右旋转
   				// t = rightRotate(t);
            }else
                t = doubleWithLeftChild(t); // 双旋转
        }
    }else if(x.compareTo(t.element) > 0){
        if(height(t.right) - height(t.left) == 2){
            if(x.compareTo(t.right.element) > 0){
                t = rotateWithRightChild(t);
            }else{
                t = doubleWithRightChild(t);
            }
        }
    }else
        ;
    t.height = max(height(t.left), height(t.right)) + 1;
    return t;
}

在这里插入图片描述

private static AVLNode rotateWithLeftChild(AVLNode k2){  // 注意,这里是右旋转! 也就是原来的根会往右下角跑
    AVLNode k1 = k2.left;
    k2.left = k1.right;
    k1.right = k2;
    k2.height = max(height(k2.left), height(k2.right)) + 1;
    k1.height = max(height(k1.left), height(k1.right)) + 1;
    return k1; // 返回的是树根!树根一定会变化!
}

在这里插入图片描述

private static AVLNode doubleWithLeftChild(AVLNode k3){
    k3.left = rotateWithRightChild(k3.left);
    k3 = rotateWithLeftChild(k3);
    return k3;
    // 一个记忆的技巧:后面的一定是右旋转,因为前面一步会变成左外侧情况!
}
2.2.3. 删除
  • 课件中只提到需要递归进行平衡维护,但是没有给出代码
  • 方法上大体与二叉搜索树一致,但是需要

2.3. 算法复杂度分析

  • 高度为0的AVL树,节点数最少是1;
  • 高度为1的AVL树,节点数最少是2;
  • 高度为2的AVL树,节点数最少是4;
  • 递推公式: N h = N h − 1 + N h − 2 + 1 N_h = N_{h-1} + N_{h-2} + 1 Nh​=Nh−1​+Nh−2​+1
    这是比较直观的,根对应1, 还需要两个尽可能小的AVL树作为左右子树,而且这两棵子树的高度差不超过1
  • N h + 1 N_h + 1 Nh​+1满足斐波那契数列,我们可以知道,节点数与层数成对数关系

3. m阶搜索树 - 无代码要求

4. B树(平衡的m阶搜索树)- 无代码要求

  • 插入看上溢出,删除看下溢出;

4.1. 插入

4.2. 删除

  • 关键是要认准节点的个数
    • 根节点:最少2个分支,1个key
    • 其他节点:最少 ( n / 2 ) 上取整 (n/2)上取整 (n/2)上取整 个分支,但是key数目要比分支数少一个
      5阶B树:最少3个分支,2个元素
  1. 尝试向左右兄弟去借,如果借的到,那么就是
    父亲下来,兄弟上去
  2. 两边都借不到,那就合并:
    父亲下来在中间,兄弟合并为一个节点
  3. 同时这件事情,需要递归向上去做

标签:lec4.1,right,null,Tree,element,Specific,else,节点,left
From: https://blog.csdn.net/lizz31/article/details/144673680

相关文章

  • QTreeView + 自定义json模型
    QTreeView使用自定义json模型前言QTreeView+自定义json模型QTreeView使用自定义json模型支持节点插入删除二、代码//QJsonModel.h#ifndefQJSONMODEL_H#defineQJSONMODEL_H#include<QAbstractItemModel>#include<QJsonDocument>#include<QJsonObject>#i......
  • CF1324F Maximum White Subtree
    看到题目最直接的想法就是以每个节点为根进行nnn次树形dp......
  • 题解:AT_abc294_g [ABC294G] Distance Queries on a Tree
    题目链接https://www.luogu.com.cn/problem/AT_abc294_g分析先不考虑修改。设\(dist_i\)表示从根节点到第\(i\)号节点的距离,\(\operatorname{lca(u,v)}\)表示树上两点\(u,v\)的最近公共祖先,那么\(u,v\)两点间的距离就是\((dist_{\operatorname{lca(u,v)}}-dist_u)+(......
  • Linux常用命令之tree命令详解
    tree是一个用于递归地以树状格式列出或显示目录内容的小型跨平台命令行程序。它不仅能够展示文件夹及其子文件夹,还能包括文件名、权限信息、符号链接等详细数据,是理解和管理文件系统结构的有力工具。功能与作用展示目录结构:tree以直观的树形图形式展示指定目录下的所有......
  • 静态 Top Tree 小记
    TopCluster系列:TopCluster树分块入门学习笔记树分块静态TopTree小记定义簇(Cluster):一个连通边集,每个簇有两个界点。界点、内点:两个簇只会在界点处有交,除了界点外其他点为内点。这两个定义也在TopCluster树分块解释过,下面用\(a(u,v)\)表示含有界点......
  • 【GreatSQL优化器-07】mm tree
    【GreatSQL优化器-07】mmtree一、mmtree介绍GreatSQL的优化器主要用mmtree也就是min-maxtree来确定条件的范围,然后根据不同索引的范围值来计算cost,选取cost最小的索引来执行SQL。下面用一个简单的例子来说明mmtree是什么。greatsql>CREATETABLEt1(c1INTP......
  • WPF TreeView实现固定表头
    1、在WPF中TreeView默认不支持固定表头的我们可以修改样式实现固定表头 新建一个TreeListView类然后继承TreeView代码如下publicclassTreeListView:TreeView,IDisposable{publicTreeListView(){//this.Loaded+=TreeListView_Loa......
  • Linux常用命令之pstree命令详解
    pstree是Linux系统中一个非常有用的命令行工具,它以树状图的形式展示进程间的关系。与传统的ps命令不同,pstree提供了一种更加直观的方式来查看哪些进程是父进程,哪些是子进程,以及它们是如何组织在一起工作的。通过这种方式,用户可以更容易地理解系统中进程的层次结构,并且......
  • 与一个方法将origin转化为tree,要求支持无限级和性能
    将一个扁平的origin数据结构转换为树形结构,并且需要支持无限级和高性能,这在前端开发中是一个常见问题。最佳方法取决于origin数据的具体格式和你的性能需求。以下提供几种方法,并分析其优缺点:方法一:递归方法(简单易懂,但可能性能较差)这种方法简单易懂,但对于大型数据集,递......
  • vue3调整el-tree样式
    vue3调整el-tree样式:deep(.el-tree){border:10px;padding:5px;background:rgba(7,36,77,0);height:calc(100%-49px)!important;color:#fff;overflow-y:auto;overflow-x:hidden;padding-right:20p......