AVL树----java

                                                                                    AVL树----java

AVL树是高度平衡的二叉查找树

1.单旋转LL旋转


理解记忆:1.在不平衡的节点的左孩子的左孩子插入导致的不平衡,所以叫LL

private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> k2) {AVLTreeNode<T> k1;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), k2.height) + 1;return k1;
}

2.单旋转RR


理解记忆:1.不平衡节点的右孩子的有孩子插入导致的不平衡,所以叫RR

private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k1) {AVLTreeNode<T> k2;k2 = k1.right;k1.right = k2.left;k2.left = k1;k1.height = max( height(k1.left), height(k1.right)) + 1;k2.height = max( height(k2.right), k1.height) + 1;return k2;
}
3.双旋转LR

理解记忆:1.不平衡节点的左孩子的有孩子导致的不平衡,所以叫LR

                     2.须要先对k1  RR,再对根K3  LL

private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {k3.left = rightRightRotation(k3.left);return leftLeftRotation(k3);
}
4.双旋转RL


理解记忆:1.不平衡节点的右孩子的左孩子导致的不平衡,所以叫RL

                     2.须要先对k3 LL,在对k1 RR

private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {k1.right = leftLeftRotation(k1.right);return rightRightRotation(k1);
}
5.AVL的样例

遍历,查找等和二叉查找树一样就不在列出,主要是 插入 删除


public class AVLTree<T extends Comparable<T>> {private AVLTreeNode<T> mRoot;    // 根结点// AVL树的节点(内部类)class AVLTreeNode<T extends Comparable<T>> {T key;                // keyword(键值)int height;         // 高度AVLTreeNode<T> left;    // 左孩子AVLTreeNode<T> right;    // 右孩子public AVLTreeNode(T key, AVLTreeNode<T> left, AVLTreeNode<T> right) {this.key = key;this.left = left;this.right = right;this.height = 0;}}// 构造函数public AVLTree() {mRoot = null;}/** 获取树的高度*/private int height(AVLTreeNode<T> tree) {if (tree != null)return tree.height;return 0;}public int height() {return height(mRoot);}/** 比較两个值的大小*/private int max(int a, int b) {return a>b ? a : b;}/** 前序遍历"AVL树"*/private void preOrder(AVLTreeNode<T> tree) {if(tree != null) {System.out.print(tree.key+" ");preOrder(tree.left);preOrder(tree.right);}}public void preOrder() {preOrder(mRoot);}/** 中序遍历"AVL树"*/private void inOrder(AVLTreeNode<T> tree) {if(tree != null){inOrder(tree.left);System.out.print(tree.key+" ");inOrder(tree.right);}}public void inOrder() {inOrder(mRoot);}/** 后序遍历"AVL树"*/private void postOrder(AVLTreeNode<T> tree) {if(tree != null) {postOrder(tree.left);postOrder(tree.right);System.out.print(tree.key+" ");}}public void postOrder() {postOrder(mRoot);}/** (递归实现)查找"AVL树x"中键值为key的节点*/private AVLTreeNode<T> search(AVLTreeNode<T> x, T key) {if (x==null)return x;int cmp = key.compareTo(x.key);if (cmp < 0)return search(x.left, key);else if (cmp > 0)return search(x.right, key);elsereturn x;}public AVLTreeNode<T> search(T key) {return search(mRoot, key);}/** (非递归实现)查找"AVL树x"中键值为key的节点*/private AVLTreeNode<T> iterativeSearch(AVLTreeNode<T> x, T key) {while (x!=null) {int cmp = key.compareTo(x.key);if (cmp < 0)x = x.left;else if (cmp > 0)x = x.right;elsereturn x;}return x;}public AVLTreeNode<T> iterativeSearch(T key) {return iterativeSearch(mRoot, key);}/* * 查找最小结点:返回tree为根结点的AVL树的最小结点。*/private AVLTreeNode<T> minimum(AVLTreeNode<T> tree) {if (tree == null)return null;while(tree.left != null)tree = tree.left;return tree;}public T minimum() {AVLTreeNode<T> p = minimum(mRoot);if (p != null)return p.key;return null;}/* * 查找最大结点:返回tree为根结点的AVL树的最大结点。*/private AVLTreeNode<T> maximum(AVLTreeNode<T> tree) {if (tree == null)return null;while(tree.right != null)tree = tree.right;return tree;}public T maximum() {AVLTreeNode<T> p = maximum(mRoot);if (p != null)return p.key;return null;}/** LL:左左相应的情况(左单旋转)。** 返回值:旋转后的根节点*/private AVLTreeNode<T> leftLeftRotation(AVLTreeNode<T> k2) {AVLTreeNode<T> k1;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), k2.height) + 1;return k1;}/** RR:右右相应的情况(右单旋转)。** 返回值:旋转后的根节点*/private AVLTreeNode<T> rightRightRotation(AVLTreeNode<T> k1) {AVLTreeNode<T> k2;k2 = k1.right;k1.right = k2.left;k2.left = k1;k1.height = max( height(k1.left), height(k1.right)) + 1;k2.height = max( height(k2.right), k1.height) + 1;return k2;}/** LR:左右相应的情况(左双旋转)。** 返回值:旋转后的根节点*/private AVLTreeNode<T> leftRightRotation(AVLTreeNode<T> k3) {k3.left = rightRightRotation(k3.left);return leftLeftRotation(k3);}/** RL:右左相应的情况(右双旋转)。** 返回值:旋转后的根节点*/private AVLTreeNode<T> rightLeftRotation(AVLTreeNode<T> k1) {k1.right = leftLeftRotation(k1.right);return rightRightRotation(k1);}/* * 将结点插入到AVL树中,并返回根节点** 參数说明:*     tree AVL树的根结点*     key 插入的结点的键值* 返回值:*     根节点*/private AVLTreeNode<T> insert(AVLTreeNode<T> tree, T key) {if (tree == null) {// 新建节点tree = new AVLTreeNode<T>(key, null, null);if (tree==null) {System.out.println("ERROR: create avltree node failed!");return null;}} else {int cmp = key.compareTo(tree.key);if (cmp < 0) {    // 应该将key插入到"tree的左子树"的情况tree.left = insert(tree.left, key);// 插入节点后,若AVL树失去平衡,则进行相应的调节。if (height(tree.left) - height(tree.right) == 2) {if (key.compareTo(tree.left.key) < 0)tree = leftLeftRotation(tree);elsetree = leftRightRotation(tree);}} else if (cmp > 0) {    // 应该将key插入到"tree的右子树"的情况tree.right = insert(tree.right, key);// 插入节点后,若AVL树失去平衡,则进行相应的调节。if (height(tree.right) - height(tree.left) == 2) {if (key.compareTo(tree.right.key) > 0)tree = rightRightRotation(tree);elsetree = rightLeftRotation(tree);}} else {    // cmp==0System.out.println("加入�失败:不同意加入�同样的节点!");}}tree.height = max( height(tree.left), height(tree.right)) + 1;return tree;}public void insert(T key) {mRoot = insert(mRoot, key);}/* * 删除结点(z),返回根节点** 參数说明:*     tree AVL树的根结点*     z 待删除的结点* 返回值:*     根节点*/private AVLTreeNode<T> remove(AVLTreeNode<T> tree, AVLTreeNode<T> z) {// 根为空 或者 没有要删除的节点,直接返回null。if (tree==null || z==null)return null;int cmp = z.key.compareTo(tree.key);if (cmp < 0) {        // 待删除的节点在"tree的左子树"中tree.left = remove(tree.left, z);// 删除节点后,若AVL树失去平衡,则进行相应的调节。if (height(tree.right) - height(tree.left) == 2) {AVLTreeNode<T> r =  tree.right;if (height(r.left) > height(r.right))tree = rightLeftRotation(tree);elsetree = rightRightRotation(tree);}} else if (cmp > 0) {    // 待删除的节点在"tree的右子树"中tree.right = remove(tree.right, z);// 删除节点后,若AVL树失去平衡,则进行相应的调节。if (height(tree.left) - height(tree.right) == 2) {AVLTreeNode<T> l =  tree.left;if (height(l.right) > height(l.left))tree = leftRightRotation(tree);elsetree = leftLeftRotation(tree);}} else {    // tree是相应要删除的节点。// tree的左右孩子都非空if ((tree.left!=null) && (tree.right!=null)) {if (height(tree.left) > height(tree.right)) {// 假设tree的左子树比右子树高;// 则(01)找出tree的左子树中的最大节点//   (02)将该最大节点的值赋值给tree。//   (03)删除该最大节点。// 这相似于用"tree的左子树中最大节点"做"tree"的替身;// 採用这样的方式的优点是:删除"tree的左子树中最大节点"之后,AVL树仍然是平衡的。AVLTreeNode<T> max = maximum(tree.left);tree.key = max.key;tree.left = remove(tree.left, max);} else {// 假设tree的左子树不比右子树高(即它们相等,或右子树比左子树高1)// 则(01)找出tree的右子树中的最小节点//   (02)将该最小节点的值赋值给tree。//   (03)删除该最小节点。// 这相似于用"tree的右子树中最小节点"做"tree"的替身;// 採用这样的方式的优点是:删除"tree的右子树中最小节点"之后,AVL树仍然是平衡的。AVLTreeNode<T> min = maximum(tree.right);tree.key = min.key;tree.right = remove(tree.right, min);}} else {AVLTreeNode<T> tmp = tree;tree = (tree.left!=null) ? tree.left : tree.right;tmp = null;}}return tree;}public void remove(T key) {AVLTreeNode<T> z; if ((z = search(mRoot, key)) != null)mRoot = remove(mRoot, z);}/* * 销毁AVL树*/private void destroy(AVLTreeNode<T> tree) {if (tree==null)return ;if (tree.left != null)destroy(tree.left);if (tree.right != null)destroy(tree.right);tree = null;}public void destroy() {destroy(mRoot);}/** 打印"二叉查找树"** key        -- 节点的键值 * direction  --  0,表示该节点是根节点;*               -1,表示该节点是它的父结点的左孩子;*                1,表示该节点是它的父结点的右孩子。*/private void print(AVLTreeNode<T> tree, T key, int direction) {if(tree != null) {if(direction==0)    // tree是根节点System.out.printf("%2d is root\n", tree.key, key);else                // tree是分支节点System.out.printf("%2d is %2d's %6s child\n", tree.key, key, direction==1?"right" : "left");print(tree.left, tree.key, -1);print(tree.right,tree.key,  1);}}public void print() {if (mRoot != null)print(mRoot, mRoot.key, 0);}
}

文章大量參考:http://www.cnblogs.com/skywang12345/p/3577479.html


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

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

相关文章

其实你女朋友也不是很爱你...

1 你玩她口红化妆品试试▼2 我妈介绍的相亲对象优点&#xff1a;每天主动问早缺点&#xff1a;每天只问早▼3 女儿过度高估老爸了▼4 国际油价暴跌全军出击买买买▼5 有人喜欢我吗&#xff1f;我爱吃炸鸡▼6 有厕纸的那部分人还有全球百分之50的双黄连▼7 其实生物书比较…

文末有彩蛋 | 第四周课程回顾与总结

我们在前三周的课程上&#xff08;第一周、第二周、第三周&#xff09;&#xff0c;系统讲授了 FOSS 和 COSS 的课程内容&#xff0c;第四周&#xff0c;我们开始进入 OSPO&#xff08;开源项目办公室&#xff09;的部分。本导学班在调研全球开源教育与课程的基础上&#xff0c…

win10 软路由_「保姆级」万晓博带你用软路由搭建家庭网络中心第1节-准备工作...

本章前言&#xff1a;  去年无意中在群我的一个群里大佬提起过软路由&#xff0c;那时候对这个需求并不是很大&#xff0c;所以对软路由只是名字概念而已&#xff0c;但是后面群里就一软路由这个话题 炒起来了&#xff0c;有的人说软路由就是利用自己闲置设备(PC笔记本)的或者…

【转】构建Android平台Google Map应用

http://www.moandroid.com/?p1360 Android 的新版本提供了的功能&#xff0c;通过这段视频&#xff0c;大家可以先简单了解下&#xff1a; Android 提供的地图&#xff08;Map&#xff09;功能可能是广大开发者非常关心的一个部分。到目前为止&#xff0c;开发内嵌式地图应用的…

将虚拟机转换成模板

在制作模板前&#xff0c;先要准备一个干净的操作系统&#xff0c;或者安装上经常使用的软件在虚拟机中&#xff0c;安装好后&#xff0c;将其正常关机&#xff0c;之后就可以转换成模板了。转换后的虚拟机将不会在主机管理中看到&#xff0c;而只能在模板中看到。克隆转换时克…

假如你学过高数,那你这一辈子都不会忘记这个人

▲ 点击查看2020年3月&#xff0c;菲列兹伦敦奖评奖委员会宣布&#xff0c;2020年度菲列兹伦敦奖将授予三位科学家&#xff0c;除开美国的 Vinokur 博士、以及德国的Steglich 教授以外&#xff0c;最后一位就是清华大学副校长、北京量子信息科学研究院院长薛其坤院士。薛其坤院…

.Net Core with 微服务 - 分布式事务 - TCC

上一次我们讲解了分布式事务的 2PC、3PC 。那么这次我们来理一下 TCC 事务。本次还是讲解 TCC 的原理跟 .NET 其实没有关系。TCC Try 准备阶段&#xff0c;尝试执行业务Confirm 完成业务Cancel 回滚准备阶段的业务TCC 事务其实是 2PC 的一个扩展。上一次我们说了 2PC &#xff…

第10章-管理Hadoop集群-hadoop 安全模式相关知识点

为什么80%的码农都做不了架构师&#xff1f;>>> 1、namenode启动时&#xff0c;namenode节点都做了哪些动作&#xff1f;fsimage和edits有什么变化&#xff1f; 2、namenode什么时候开始监听RPC和HTTP请求&#xff1f; namenode启动时&#xff0c;首先将映像文件(f…

oracle挂证多少钱一个月_惊呆,一条sql竟然把Oracle搞挂了

一条sql就能把oracle搞挂了&#xff0c;真的是不敢相信啊&#xff0c;前几天生产上确实出现了这样一个故障&#xff0c;我们来一起做一个事件回放。系统介绍系统架构见下图&#xff1a;fileapplication1和application2是一个分布式系统中的2个应用&#xff0c;application1连接…

linux图形界面鼠标变成小手_加载Linux系统,树莓派变身桌面电脑

开始正文前&#xff0c;我们想听听娃说了什么操作系统&#xff0c;英文名叫做Operation System&#xff0c;简写为OS&#xff0c;是电子设备运行的基础软件&#xff0c;按运行的设备类型来分&#xff0c;操作系统分为手机操作系统&#xff0c;桌面电脑操作系统和服务器操作系统…

二叉查找树转换成有序的双向链表

首先对于二叉查找树的定义和性质&#xff0c;以及如何得到二叉查找树某个节点的子树下的最大值和最小值和插入一个值的内容可以参考这两篇文章&#xff1a; &#xff08;1&#xff09;http://www.cnblogs.com/chenping-987123/archive/2010/09/25/1834341.html &#xff08;2&a…

就你这个求婚态度,能嫁给你才怪!

1 兄弟&#xff01;哪有求着婚还走神的&#xff1f;&#xff01;▼2 喝奶茶专用口罩&#xff01;▼3 把广东茶楼的菜都点一遍是什么体验&#xff1f;▼4 你觉不觉得这个门锁有点像托马斯的小火车▼5 手里的塑料袋像极了塑料兄弟情▼6 小朋友看《喜羊羊》看到的是坏人的愚…

Remoting and MSMQ 结合做的一个DEMO

真的非常感谢CnBlogs.com,因为有很多教程里写的知识点并不全面,而且也没附带例子.通过这里我学习到了很多很多.希望网站能越办越好哦.下面是我学习分布式开发时写的一个小demo,当然功能有限,技术也很低.希望大师们能拍拍砖,不吝赐教.呵呵软件运行的一个截图下面说说流程吧,1:利…

再聊一次值类型和引用类型

C#值类型&#xff0c;作为函数形参&#xff0c;形参被修改&#xff0c;不影响原值。这是我们在初始学习编程时需要记住的内容&#xff0c;我们也是一直这样践行的。先说结论&#xff1a;这是不准确的。为什么提出这样看似很浅显的问题&#xff0c;是因为有次我在使用ArraySegme…

java+字节码工具64位_jclasslib 下载-jclasslib 32位64位(java字节码查看工具) 5.1 官方版 - 河东下载站...

jclasslib是款免费的开源java字节码的查看工具&#xff1b;它支持进行查看您需要进行使用汉字运用到的Java字节码&#xff0c;并且还拥有一个的类库来让开发者进行读取&#xff0c;包括了修改、对JavaClass文件、字节码的写入等&#xff1b;用户这进行使用的过程中&#xff0c;…

ado filter 多条记录_注意!武汉江南中心绿道武九线综合管廊工程开工,青山区多条道路通行规则有变...

楚天都市报10月29日(记者吴昌华 通讯员 李佳 陈菲)今日记者从武汉交管部门获悉&#xff0c;本周六&#xff0c;10月31日&#xff0c;武汉市江南中心绿道武九线综合管廊工程开始施工&#xff0c;青山区多条道路通行规则有变&#xff0c;部分道路禁止通行。交管部门提供详细绕行建…

深度学习框架再次升级,它们都有什么优点?

全世界只有3.14 % 的人关注了爆炸吧知识经过几年的发展&#xff0c;深度学习方法摧枯拉朽般地超越了传统方法&#xff0c;成为人工智能领域最热门的技术。之后&#xff0c;谷歌、亚马逊、百度、Facebook 纷纷开源了自己的深度学习框架。而支撑AlphaGo的核心技术架构--TensorFlo…

SQL Server 2005的安装,SQL Server 2005系列之一

最近复习SQL Server 2005,忽然有了写系列的打算&#xff0c;也不知道能不能写好&#xff0c;今天先写一篇关于SQL Server 2005的安装的博文吧。和往常一样&#xff0c;我们先来看看SQL Server 2005到底是个什么东西&#xff1f;SQL Server 2005是一种以高性能、高可靠性和可用性…

Quartz - 作业调度框架-插件化开发

背景大部分业务都是基于定时的任务&#xff0c;特别适合使用quartz这类框架解决定时问题。具体quartz的使用&#xff0c;看官方文档就可以了。下面谈谈对quartz插件化的封装。我们使用quartz.plugin。然后在quartz_jobs.xml方法里面定义了schedule&#xff0c;其中灵活的地方在…

cgi备份还原和ghost有什么区别_手动GHOST还原重装系统详细教程

一键重装虽好&#xff0c;但也不是万能的。俗语说&#xff1a;治标不治本。也许你懂得用各种一键备份还原工具重装&#xff0c;但不一定懂得手动GHOST重装。为此&#xff0c;吻妻为大家分享一下如何手动GHOST还原重装系统&#xff0c;本教程步骤虽多&#xff0c;但很多都是点“…