博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
AVL树平衡旋转详解
阅读量:5277 次
发布时间:2019-06-14

本文共 1385 字,大约阅读时间需要 4 分钟。

 

AVL树平衡旋转详解

概述

  AVL树又叫做平衡二叉树。前言部分我也有说到,AVL树的前提是二叉排序树(或叫做二叉查找树)。由于在生成BST树的过程中可能会出现线型树结构,比如插入的顺序是:1, 2, 3, 4, 5, 6, 7..., n。在BST树中,比较理想的状况是每个子树的左子树和右子树的高度相等,此时搜索的时间复杂度是log(N)。可是,一旦这棵树演化成了线型树的时候,这个理想的情况就不存在了,此时搜索的时间复杂度是O(N),在数据量很大的情况下,我们并不愿意看到这样的结果。

  现在我们要做的事就是让BST在创建的过程中不要向线型树发展。方法就是让其在添加新节点的时候,不断调整树的平衡状态。

  定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。

 

AVL树实现

1.节点失衡

  我们对于节点平衡有这样的定义:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。而这里提到的高度差,就是我们下面会引入的平衡因子:BF(balance factor)

  因为AVL树说到底还是一个二叉树,只有两个子节点。而且节点失衡的发生,是因为有一个新节点的插入,这个新插入的节点导致了某些节点左右子节点高度的不一致。所以我们可以枚举出以下4种情况的失衡状态。

(1)在一个节点的左子树的左子树上插入一个新节点。即LL。在这种情况下,我们可以通过将节点右旋使其平衡。如图-2所示

图-2 LL单右旋操作

原A的左孩子B变为父结点,A变为其右孩子,而原B的右子树变为A的左子树,注意旋转之后Brh是A的左子树

 

(2)在一个节点的右子树的右子树上插入一个新节点。即RR。在这种情况下,我们可以通过将节点左旋使其平衡。如图-3所示;

图-3 RR单左旋操作

这时只需要把树向左旋转一次即可,如图所示,原A右孩子B变为父结点,A变为其左孩子,而原B的左子树Blh将变为A的右子树。

(3)在一个节点的左子树的右子树上插入一个新节点。即LR。在这种情况下,我们不能直接通过将节点左旋或右来使其平衡了。这里需要两步来完成,先让树中高度较低的进行一次左旋(RR型),这个时候就变成了LL了。再进行一次单右旋操作即可。如图-4所示;

图-4 LR先左旋再右旋操作

 

这时需要旋转两次,仅一次的旋转是不能够使二叉树再次平衡。如图所示,在B节点按照RR型向左旋转一次之后,二叉树在A节点仍然不能保持平衡,这时还需要再向右旋转一次。

 

(4)在一个节点的右子树的左子树上插入一个新节点。即RL。在这种情况下,我们不能直接通过将节点左旋或右来使其平衡了。这里需要两步来完成,先让树中高度较低的进行一次右旋,这个时候就变成了RR了。再进行一次单左旋操作即可。如图-5所示;

图-5 RL先右旋再左旋操作

 

平衡二叉树某一节点的右孩子的左子树上插入一个新的节点,使得该节点不再平衡。同样,这时需要旋转两次,旋转方向刚好同LR型相反。

  从上面对节点失衡的说明,以及图解。我想你已经对旋转的操作有了一个大概地认识了吧。从图中我们也可以看出,LL型和RR型、LR型和RL型是两个行为很相似地操作。其实他们互为对称。

代码见这里

转载于:https://www.cnblogs.com/ldq2016/p/10505036.html

你可能感兴趣的文章
anjularjs 路由
查看>>
【洛谷】P2179 [NOI2012]骑行川藏
查看>>
Python函数篇
查看>>
Grid布局和Flex布局
查看>>
关于weblogic server对docker的支持
查看>>
Filter 字符编码Filter 一
查看>>
codevs2574 波兰表达式
查看>>
利用zookeeper实现发布订阅模式
查看>>
C\C++对文件的读写操作
查看>>
构建工具
查看>>
pycharm pull到github
查看>>
深入理解JVM类加载机制
查看>>
KTV点歌系统
查看>>
setTimeout and jquery
查看>>
HDU-3480 Division (四边形不等式优化DP)
查看>>
ThinkPHP5显示数据库字段内容
查看>>
vue项目中开启Eslint碰到的一些问题及其规范
查看>>
循环队列实现
查看>>
获取表单提交的数据getParameter()方法
查看>>
CSS层模型
查看>>