[树结构]平衡二叉树AVL

平衡二叉树是一种二叉排序树,其中每一个节点的左子树和右子树的高度至多等于1,平衡二叉树又称为AVL树。

将二叉树节点的左子树深度减去右子树深度的值称为平衡因子BF,平衡二叉树上所有节点的平衡因子只可能是-1,0或者1。

距离插入点最近的,且平衡因子的绝对值大于1的结点为根的子树,我们称为最小不平衡子树。

平衡二叉树实现原理

先来看一个例子:

对于数组a[10]={3,2,1,4,5,6,7,10,9,8}构建平衡二叉树。

按照二叉排序树的方式插入新的元素,当插入1的时候,使得当前二叉树失去平衡:

当插入5的时候,使得平衡二叉树再次失去平衡:

插入6的时候,同样产生不平衡:

注意:上面的这些不平衡都有一个共同的特点,那就是最小不平衡子树的根的BF同它的孩子(左孩子或者右孩子)的BF是同号的。所以这是仅需要一次旋转就可以了

当插入到数字9的时候,同样的发生了不平衡:

从上面的图可以看到一次的旋转是不能做到再次的平衡的。所以要两次旋转。

在插入8的时候,同样的发生了不平衡,同样的需要两次调整:

所以总结上面的过程:

当最小不平衡子树根节点的平衡因子BF是大于1的时候,就右旋,小于-1时就左旋。

插入节点后,最小不平衡子树的BF与它的子树的BF符号相反时,就需要对子树节点先进行一次旋转,以使得符号相同后,在反向旋转一次才能够完成平衡操作。

平衡二叉树算法实现

加入了平衡因子,所以在每一个结点中增加一个数据域,这个数据域表示以这个结点为根的二叉树的平衡因子。所以树结点的定义为:

typedef struct BiTNode
{int data;int bf;struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

其实对于二叉平衡树的每一次的调整都可以分成两个步骤:

  • 调整各个结点的BF值
  • 旋转子树结构

先写旋转子树结构代码:

void R_Rotate(BiTree *T)
{BiTree tmp;tmp = (*T)->lchild;(*T)->lchild = tmp->rchild;tmp->rchild = (*T);*T = tmp;
}void L_Rotate(BiTree *T)
{BiTree tmp;tmp = (*T)->rchild;(*T)->rchild = tmp->lchild;tmp->lchild = (*T);*T = tmp;
}

所以当插入一个新的结点,导致树结构不平衡的时候,当树右边超重的时候,要右平衡:(树主体左旋转)

//右平衡,右子树超重
void RightBalance(BiTree *T)
{BiTree tmp, tmpr;tmp = (*T)->rchild;switch (tmp->bf){case -1:(*T)->bf = 0;tmp->bf = 0;L_Rotate(T);break;case 1:tmpr = tmp->lchild;switch (tmpr->bf){case 1:tmp->bf = -1;(*T)->bf = 0;break;case -1:tmp->bf = 0;(*T)->bf = 1;break;case 0:tmp->bf = (*T)->bf = 0;}tmpr->bf = 0;//R_Rotate(&tmp);是错误的,因为不能修改上一级的指针R_Rotate(&(*T)->rchild);L_Rotate(T);}
}

当插入一个结点导致树结构不平衡的时候,左子树超重,要左平衡:(树主体右旋转)

//左平衡,左子树超重
void LeftBlance(BiTree *T)
{BiTree tmp,tmpr;tmp = (*T)->lchild;switch (tmp->bf){case 1:(*T)->bf = 0;tmp->bf = 0;R_Rotate(T);break;case -1:tmpr = tmp->rchild;switch (tmpr->bf){case 1:tmp->bf = 0;(*T)->bf = -1;break;case -1:tmp->bf = 1;(*T)->bf = 0;break;case 0:(*T)->bf = 0;tmp->bf = 0;break;}//switchtmpr->bf = 0;//L_Rotate(&tmp);是错误的,因为不能修改上一级的指针L_Rotate(&(*T)->lchild);R_Rotate(T);}
}

注意:上面两处的双旋转的时候,不能旋转tmp,因为这样不能把父结点的指针修改,所以要旋转父结点指下来得指针。

 最后插入操作的主函数:

bool InsertAVL(BiTree *T, int key, bool *taller)
{if (*T ==NULL){*T = (BiTree)malloc(sizeof(BiTNode));(*T)->data = key;(*T)->lchild = (*T)->rchild = NULL;(*T)->bf = 0;*taller = true;return true;}if((*T)->data == key){*taller = false;return false;}else if((*T)->data > key){if(!InsertAVL(&(*T)->lchild, key, taller))return false;if(*taller){switch ((*T)->bf){case 1:LeftBlance(T);*taller = false;break;case 0:(*T)->bf = 1;*taller = true;break;case -1:(*T)->bf = 0;*taller = false;break;}//switch}//if}//else ifelse	//(*T)->data < key{if (!InsertAVL(&(*T)->rchild, key, taller))return false;if(*taller){switch ((*T)->bf){case 1:(*T)->bf = 0;*taller = false;break;case 0:(*T)->bf = -1;*taller = true;break;case -1:RightBalance(T);*taller = false;}//switch}//if}//elsereturn true;
}

  

  

转载于:https://www.cnblogs.com/stemon/p/4839019.html

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

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

相关文章

dedecms php5.4 无法退出后台,PHP5.4版本织梦dedecms后台退出空白的解决方法

你是否遇到过PHP5.4版本织梦dedecms后台退出空白的问题&#xff0c;有没有解决呢?没有解决思绪&#xff0c;就来看看我这篇文章吧。解决办法&#xff1a;打开include/userlogin.class.php找到&#xff1a;function exitUser(){ClearMyAddon();session_unregister($this->ke…

C++构造函数/析构函数 设置成private的原因

C构造函数/析构函数 设置成private的原因 标签&#xff08;空格分隔&#xff09;&#xff1a; c/c 将构造函数&#xff0c;析构函数声明为私有和保护的&#xff0c;那么对象如何创建&#xff1f; 已经不能从外部调用构造函数了&#xff0c;但是对象必须被构造&#xff0c;应该如…

R语言学习笔记(4)

第四章&#xff1a;基本数据管理 一 贯穿整章的示例 二 变量的创建、重编码和重命名 三 日期值与缺失值 四 数据类型和类型转换 五 数据集的排序、合并与取子集 一 贯穿整章的示例&#xff08;leadership&#xff09; 代码4-1 1 > manager<-c(1,2,3,4,5)2 > date<…

php substr_replace 中文乱码,php substr_replace替换字符串一些实例_PHP教程

substr_replace与str_replace有一点像就是直接把字符串替换一部份了&#xff0c;下面小编来给各位同学介绍一下操作方法。substr_replace() 函数把字符串的一部分替换为另一个字符串。用法substr_replace(string,replacement,start,length)注意当字符串包含中文时&#xff0c;不…

发布《Linux工具快速教程》

发布《Linux工具快速教程》 阶段性的完成了这本书开源书籍&#xff0c;发布出来给有需要的朋友&#xff0c;同时也欢迎更多的朋友加入进来&#xff0c;完善这本书&#xff1b; 本书Github地址&#xff1a;https://github.com/me115/linuxtools_rst 在线阅读 缘起 Linux下有很多…

java6:流程控制

Java 流程控制&#xff1a;顺序分支循环分支&#xff1a;if(布尔表达式){语句块}else{语句块}尽量使用肯定条件&#xff0c;减少else&#xff0c;减少嵌套package day06; import java.util.Scanner; public class Demo01 {public static void main(String[] args) {Scanner con…

linux 部署php svn,Linux服务器搭建svn环境方法详解

下面由Linux教程栏目给大家介绍Linux服务器搭建svn环境的方法&#xff0c;希望对需要的朋友也是帮助&#xff01;1、安装svn服务端sudo apt-get install subversion2、安装svn在ubuntu的本地客户端sudo apt-get install libapache2-svn3、在根目录home下面建一个文件夹svn&…

pfsense 2.2RC版本应用

为什么要上RC版本呢&#xff1f;因为华硕主板有一个RTL8111G驱动在2.15中还没有识别。。。。 公司双线WAN&#xff0c;一个PPPOE一个静态IP。 开了端口转发&#xff0c; 要求对不同的IP进行相关限速&#xff0c; 到达指定网站用固定IP&#xff0c; 两根线带宽均衡使用。 相关设…

我的Android进阶之旅------Android利用温度传感器实现带动画效果的电子温度计

要想实现带动画效果的电子温度计&#xff0c;需要以下几个知识点&#xff1a;1、温度传感器相关知识。2、ScaleAnimation动画相关知识&#xff0c;来进行水印刻度的缩放效果。3、android:layout_weight属性的合理运用&#xff0c;关于android:layout_weight属性的讲解&#xff…

com组件的注册

错误&#xff1a; 检索 COM 类工厂中 CLSID 为 {79AD7B73-C515-40B4-8B02-CB0F5FA5A1A8} 的组件失败&#xff0c;原因是出现以下错误: 80040154 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))。 解决方案&#xff1a; 用regsvr32 dll路径 进行dll的注册。转…

mybatis中的#和$的区别

为什么80%的码农都做不了架构师&#xff1f;>>> 1. #将传入的数据都当成一个字符串&#xff0c;会对自动传入的数据加一个双引号。如&#xff1a;order by #user_id#&#xff0c;如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是…

ecshop pages.lbi.php,关于Ecshop pages.lbi.php Xss漏洞的修复

前段时间在用ecshop建站的时候&#xff0c;360报警说出现了严重的漏洞&#xff1a;Ecshoppages.lbi.phpXss漏洞我是分割线前段时间在用ecshop建站的时候&#xff0c;360报警说出现了严重的漏洞&#xff1a;Ecshop pages.lbi.php Xss漏洞我是分割线描述&#xff1a;目标存在跨站…

php递归操作目录 递归对参数转义

header("Content-type:text/html;charsetutf-8"); //递归读取目录 function reddir($path,$level0) {$dh opendir($path);while(($row readdir($dh)) ! false){if($row . || $row ..)continue;echo str_repeat(&nbsp,$level*6) . $row . <br />;if(is…

MINA2 源代码学习--源代码结构梳理

一、mina总体框架与案例&#xff1a; 1.总体结构图&#xff1a; 简述&#xff1a;以上是一张来自网上比較经典的图&#xff0c;总体上揭示了mina的结构&#xff0c;当中IoService包括clientIoConnector和服务端IoAcceptor两部分。即不管是client还是服务端都是这个结构。IoServ…

matlab水力学工具箱,新浪潮水工设计软件

新浪潮水工设计工具箱是一款强大的水利电力工程设计辅助软件&#xff0c;集合了结构设计、水闸设计、挡土墙设计、地基基础设计、水力学计算、堤防设计及查询工具7个模块的40多个程序&#xff0c;为从事水利电力工程设计用户的设计工作提供了多种便利。主要功能一、结构设计1、…

[BZOJ 1026] [SCOI 2009] Windy数 【数位DP】

题目链接&#xff1a;BZOJ - 1026 题目分析 这道题是一道数位DP的基础题&#xff0c;对于完全不会数位DP的我来说也是难题.. 对于询问 [a,b] 的区间的答案&#xff0c;我们对询问进行差分&#xff0c;求 [0,b] - [0,a-1] 的答案。这样就化繁为简了。 具体过程见代码中的注释。 …

求一个简单的php购物车,PHP简单实现购物车

首先&#xff0c;判断是否登录、if(isset($_session[‘user_id‘])){存在&#xff1b;把用户id和商品id&#xff0c;加入购物车表}else{不存在&#xff1b;使用cookie把商品ID和主机IP放入一个数组&#xff0c;把这个数组存入cookie&#xff1b;浏览器允许存放300个cookie&…

如何查看mac系统是32位还是64位的操作系统

&#xff08;一&#xff09;点击工具栏左上角点击 &#xff08;苹果Logo&#xff09;标志&#xff0c;关于本机 --> 更多信息 --> 系统报告 -->(左侧栏中)软件 &#xff08;二&#xff09;打开终端&#xff0c;输入命令 uname -a 回车 x86_64 表示系统为64位 i68…

3ds max删除了对象后,还是将原来所有对象输出的原因

原因是场景中除了 几何体 外还有 图形&#xff0c;如下图 将这些图形删除&#xff0c;几何体就都正常输出了。 转载于:https://www.cnblogs.com/qingsunny/p/4236530.html

后代选择器

1 <!DOCTYPE HTML>2 <html>3 <head>4 <meta http-equiv"Content-Type" content"text/html; charsetutf-8">5 <title>后代选择器</title>6 <style type"text/css">7 .first span{8 color:red;9 …