AVL树(平衡二叉树)讲解,入门篇,适合新手观看

1.1 概念

平衡二叉树就是为了让二叉搜索树的平均查找长度更短,时间复杂度更靠近logN,如果一个二叉搜索树不平衡了就会出现图1情况,完全变成一个数组,时间复杂度也变为了O(N)。
平衡因子:平衡因子就是针对于树中某一结点,它的左子树高度减去右子树的高度所得结果就是它的平衡因子,如果这个平衡因子的绝对值等于2的话,那么这个树就认为出现了不平衡状况,我们就需要修正这个树,缩小它的平衡因子,缩小平衡因子,也就是让树的左右两端高度更均匀平衡,让高度越靠近log2N+1(N个结点构成的二叉树的高度)。
在这里插入图片描述

查找长度:查找长度就是查找运算中需要比较的次数,树的高度越小,查找长度就越小,查找效率就越高。它的定义如下:在这里插入图片描述

n为查找表中元素个数,Pi为查找第i个元素的概率,通常假设每个元素查找概率相同,Pi=1/n,Ci是找到第i个元素的比较次数,显然AVL树中每个节点的比较次数与它所在的层数有关,AVL树本质还是二叉搜索树,二叉搜索树又与线性二分查找一样。
这个集合中,找到每个数的概率都相同,为1/9,第一次查找,就是数组中间那个元素也就是5,第二次查找,有两个方向,向右或者向左指向2或者7,第三次查找有四种可能(1 or 3 or 6 or 8 ) ,第四次有两种可能(4 or 9) ,于是可以算出期望1x1/9+2x2/9+3x4/9+4x2/9=25/9,也就是我们给出一个数,平均要比较两次就能找到,将这个数组抽象为二叉搜索树,通过查找长度公式也能得出这棵树的平均查找长度是25/9。
在这里插入图片描述

1.2 修正树,缩小平衡因子的方法

第一种(左旋)
如果插入一个结点(插入点)到另一个结点A的左儿子的左子树而导致树失衡的话,也就是三点连成一条直线(A,A左儿子,插入点),那么我们采用左旋来解决这种情况,我们旋转时以谁为支点,旋转它的子树呢?是以最先发现树不平衡的那位结点,也就是从下往上,第一个平衡因子为2的那个结点。

在这里插入图片描述

首先8肯定是最先发现树不平衡的结点,此时以8为支点,将它的子树向左(顺时针)移动,想象着把他它的子树装进麻袋里看作一个整体来进行移动,最后移动到位置后再拆开,此时树结构会发生变化,由于5结点的right指向了8,6这个点变得孤立无援,但由于树结构发生变化,点8的left是空着的,于是就让支点8的left的来指向它。
左旋模板
在这里插入图片描述


第二种(右旋)
如果插入一个结点(插入点)到另一个结点A的右儿子的右子树而导致树失衡的话,也就是三点连成一条直线(A,A右儿子,插入点),那么我们采用左旋来解决这种情况。
右旋模板
在这里插入图片描述
可以看见A与A的右儿子B,以及插入点,这三点构成向右的一条直线


第三种 左右旋:如果插入一个结点(插入点)到另一个结点A的左儿子的右子树而导致树失衡的话,也就是三点连不成一条直线(A,A左儿子,插入点),那么我们采用左右旋来解决这种情况,左右旋实际就是以A的左儿子为支点对它的右子树进行一次右旋,然后以A为支点对它左子树进行一次左旋


第四种 右左旋:如果插入一个结点(插入点)到另一个结点A的右儿子的左子树而导致树失衡的话,也就是三点连不成一条直线(A,A右儿子,插入点),那么我们采用右左旋来解决这种情况,右左旋实际就是以A的右儿子为支点对它的左子树进行一次左旋,然后以A为支点对它右子树进行一次右旋


java代码实现

class AVLTree {Tree root;public void Insert(int Data){root=Tree.InsertNode(root,Data);}public void Inorder(){Tree.Inorder(root);}public int Height(){return Tree.MaxHeight(root);}
}public class Tree {Tree left;Tree right;int Data;public Tree(int Data){this.Data=Data;}public  static Tree InsertNode(Tree root, int Data){if(root==null){Tree node = new Tree(Data);return node;}else {if (Data > root.Data) {//插入的是右子树root.right = InsertNode(root.right, Data);if(MaxHeight(root.left)-MaxHeight(root.right)==-2){if(Data>root.right.Data)//右旋root=rightTrans(root);elseroot=right_left_Trans(root);}} else if (Data <= root.Data) {//插入的左子树root.left = InsertNode(root.left, Data);if(MaxHeight(root.left)-MaxHeight(root.right)==2){if(Data<root.left.Data)//左旋root=rightTrans(root);elseroot=left_right_Trans(root);}}}return root;}public static Tree Delete(Tree node, int Data){if(node==null){return null;   //未找到}//先找到要删除的节点if(Data>node.Data){node.right = Delete(node.right,Data);}elseif(Data<node.Data){node.left = Delete(node.left,Data);}else{//找到了if(node.left!=null && node.right!=null){node.Data=findInsteadNode(node.left);Delete(node.left,Data);}else{if(node.right!=null)node=node.right;elseif(node.left!=null)node=node.left;elsenode=null;}}return node;}public static int findInsteadNode(Tree node){if(node.right!=null)return findInsteadNode(node.right);elsereturn node.Data;}public static void Inorder(Tree node){if(node!=null){Inorder(node.left);System.out.println(node.Data+" ");Inorder(node.right);}}//高度计算函数public static int MaxHeight(Tree node){int leftHeight,rightHeight;if(node!=null){leftHeight=MaxHeight(node.left);rightHeight=MaxHeight(node.right);return (leftHeight>rightHeight ?leftHeight:rightHeight)+1;}return 0;}//右旋public static Tree rightTrans(Tree A){Tree B=A.right;A.right=B.left;B.left=A;return B;}//左右旋public static Tree left_right_Trans(Tree A){Tree B=A.left;A.left=rightTrans(B);return leftTrans(A);}//左旋public static Tree leftTrans(Tree A){Tree B=A.left;A.left=B.right;B.right=A;return B;}//右左旋public static Tree right_left_Trans(Tree A){Tree B=A.right;A.right=leftTrans(B);return rightTrans(A);}public static void main(String[] args) {AVLTree avlTree = new AVLTree();avlTree.Insert(10);avlTree.Insert(15);avlTree.Insert(5);avlTree.Insert(3);avlTree.Insert(8);avlTree.Insert(6);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读源码,对开发者重要吗?

.NET 5.0 Peview 2发布4月2日&#xff0c;微软发布了.NET 5.0 Preview 2&#xff0c;带来功能和性能方面的改进。这一版本包括.NET 5.0.0 Preview 2与.NET SDK 5.0.100 Preview 2。.NET 5是.NET Framework和.NET Core的未来&#xff0c;最终将成为一个统一平台&#xff0c;.NET…

Redis和DB数据一致性解决方案

问题出现原因 并发时候无法保证读写的先后顺序&#xff0c;如果删掉了缓存还没来得及写库&#xff0c;另外一个县城就多来读取&#xff0c;发现缓存为空就去读取数据库并且写入缓存&#xff0c;这时候缓存中就是脏数据如果先写库&#xff0c;在删除缓存前&#xff0c;写库的线…

数据结构堆的时间复杂度(最大堆,最小堆)

创建堆的方式有两种&#xff0c;一种是一边插入结点&#xff0c;一边调用堆的插入方法调整堆&#xff0c;这样的时间复杂度就是 O(NlogN)&#xff0c;而第二种方式就把时间复杂度缩减到了O(N)&#xff0c;它是采用先把结点插入好了&#xff0c;然后再来调整堆&#xff0c;并不是…

中国速度之二神山建设(3):有力的技术保障,基建世界里的云原生缩影 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩丰…

Rx2.0后台开发分享

Rxjava2.x 微软的一个函数库&#xff0c;Rx是一个编程模型&#xff0c;模板是提供一致的编程接口&#xff0c;帮助开发者更方便的处理异步数据流&#xff0c;现在Rx已经支持几乎全部的流行编程语言。比较流行的有Rxjava&#xff0c;RxJs&#xff0c;Rx.NET&#xff0c;社区网站…

中国速度之二神山建设(4):全能运维,召之即来,来之即战 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩丰…

Spring Cloud部分源码分析Eureka,Ribbon,Feign,Zuul

Eureka SpringCloud Eureka使用NetFlix Eureka来实现的&#xff0c;它包括了服务端组件和客户端组件&#xff0c;并且都是用java 编写的。 Eureka服务端就是服务注册中心&#xff0c;Eureka客户端主要处理服务的注册发现&#xff0c;通过注解和参数配置的方式&#xff0c;客户…

C++ class实现邻接表存储的图(完整代码)

代码如下: #include <iostream> #include <queue>using namespace std; const int MaxVertexNum 30; typedef int InfoType; typedef int VertexType;class Node {friend class VNode;friend class ALGraph; private:int adjvertex;InfoType info;Node *next; };…

世界上首个被数学证明安全的OS微内核seL4成立基金会

Linux 基金会正在与澳大利亚国家科学机构 CSIRO 合作&#xff0c;打造 seL4 操作系统微内核生态。近日 Linux 基金会宣布托管 seL4 基金会&#xff0c;该基金会以澳大利亚国家科学机构 CSIRO 的数字机构 Data61 创建的 seL4 操作系统微内核为基础项目。seL4 是一个安全操作系统…

数据结构(哈夫曼树,哈夫曼编码)入门篇,JAVA实现

什么是哈夫曼树 哈夫曼树就是一种最优判定树&#xff0c;举个例子&#xff0c;如下一个判断逻辑 if(s<60) g1; else if(s<70) g2 else if(s<80) g3 else if(s<90) g4 else g5; 分数概率图如下 如果按照代码从上到下顺序构造判定树&#xff0c;那么如下图所示&am…

C++ class实现十字链表存储的图(完整代码)

代码如下: #include <iostream> #include <queue> using namespace std; typedef int InfoType; typedef int VertexType; const int MaxVertexNum 30;class ArcNode {friend class OLGraph;friend class VertexNode; private:int tailvertex, headvertex;ArcNod…

hystrix隔离策略对比

hystrix隔离策略 zuul的隔离实现是基于hystrix实现的&#xff0c;hystrix支持线程池隔离和信号量的隔离 # 信号量隔离&#xff1a; it executes on the calling thread and concurrent requests are limited by the semaphore count --引自官网单每次调用线程&#xff0c;当…

中国速度之二神山建设(1):坚强的领导核心,“小团队大后台”组织结构 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩丰…

通过Java编写一个服务器理解动态Web,静态Web

静态Web 说到Servlet自然就要说到Web,Web分为静态Web和动态Web&#xff0c;之前我一直都傻傻分不清两者的区别&#xff0c;直到用JAVA编写了一个服务器后才明白二者的区别&#xff0c;所谓静态Web&#xff0c;实际上就是指&#xff0c;客户端要请求的资源文件&#xff0c;服务器…

Hystrix在网关Zuul使用中遇到问题

Hystrix在网关Zuul使用中遇到问题 Zuul默认隔离策略级别是信号量隔离&#xff0c;默认最大隔离信号量是100 信号量隔离和线程隔离的区别&#xff1a;https://blog.csdn.net/liaojiamin0102/article/details/94394956默认的设置如源码&#xff1a; //在ZuulProperties 类下游…

C++ 实现无向图的最小生成树Prim算法(附完整代码)

实现Prim算法&#xff0c;需设置两个辅助一维数组lowcost和closevertex。 其中lowcost用来保存集合V-U中各顶点与集合U中各顶点构成的边中具有最小权值的边的权值&#xff1b;数组closevertex用来保存依附于该边的在集合U中的顶点。 过程: 假设初始状态时&#xff0c;U{u0}&a…

中国速度之二神山建设(2):完善的项目计划,高效能价值流 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末。&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩…

C++ 实现无向图的最小生成树Kruskal算法(完整代码)

按照Kruskal思想&#xff0c;n个结点的生成树有n-1条边&#xff0c;故反复上述过程&#xff0c;直到选取了n-1条边为止&#xff0c;就构成了一棵最小生成树。 实现Kruskal算法的关键问题是&#xff1a; 当一条边加入T的边集中后&#xff0c;如何判断是否构成回路。 一种解决方…

MySql 内连接,外连接查询方式区别

MySql 内连接&#xff0c;外连接查询方式 CREATE TABLE question_test (q_id int(11) DEFAULT NULL,q_name varchar(10) DEFAULT NULL,q_part varchar(10) DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8CREATE TABLE answer_test (a_id int(11) DEFAULT NULL,a_name varch…

让我的 .NET Core 博客系统支持 Docker

点击上方蓝字关注“汪宇杰博客”导语我的博客&#xff08;https://edi.wang&#xff09;所使用的博客系统 Moonglade 开源已经一年多了。目前已有至少4位社区朋友使用此系统在 Azure、阿里云上部署了自己的博客。可惜长久以来该系统一直缺乏 Docker 支持&#xff0c;而 .NET Co…