html中avl地址,【数据结构】什么是AVL树

什么是AVL树

二叉查找树的一个局限性就是有可能退化成一个链表,这种情况下二叉查找树的效率就会急剧下降变成0(n)。而AVL树可以很好地解决BST的这种困境。本篇博客会介绍AVL树的基本特点和相关操作。

1. 什么是AVL树

任何两个子树的高度差最大是1,这样的二叉树叫做AVL树。

先来确定几个概念:

平衡因子:将二叉树上节点的左子树高度减去右子树高度的值称为该节点的平衡因子BF(Balance Factor)。

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

e26c0f699c16454d0def133b8cfea893.png

左边二叉树的节点45的BF = 1,插入节点43后,节点45的BF=2。

节点45是距离插入点43最近的BF不在[-1,1]范围内的节点,因此以节点45为根的子树为最小不平衡子树。

2. 节点的实现

public class AVLTreeNode {

// 存储的数据-用于排序

T key;

// 节点高度-用于计算父节点的BF

int height;

// 左儿子 & 右儿子

AVLTreeNode left;

AVLTreeNode right;

public AVLTreeNode() {

}

public AVLTreeNode(T key, AVLTreeNode left, AVLTreeNode right) {

this.key = key;

this.left = left;

this.right = right;

this.height = 0;

}

}

节点的定义还是比较简单的,相对于之前的定义多了一个height属性用于计算父节点的BF。

树的定义

public class AVLTree {

// 定义树的根节点

AVLTreeNode root;

public AVLTree() {

root = null;

}

}

获取树的高度

public int height() {

return height(root);

}

private int height(AVLTreeNode tree) {

if (tree != null){

return tree.height;

}

return 0;

}

本文章将空树的高度定义为0,高度以树的层次为准,根节点的高度为1,依次类推。

3. AVL树的调整

如果在AVL树中进行插入或删除节点后,可能导致AVL树失去平衡。这种不平衡可能出现在下面四种情况中:

对a的左儿子的左子树进行一次插入。(LL)

对a的左儿子的右子树进行一次插入。(LR)

对a的右儿子的左子树进行一次插入。(RL)

对a的右儿子的右子树进行一次插入。(RR)

其中1、4是关于a点的镜像对称,2、3是关于a点的镜像对称。

第一种情况(1、4)需要通过对树的一次单旋转完成调整。

第二种情况(2、3)需要通过对树的一次双旋转完成调整。

3.1 LL旋转

在左子树上插入左孩子导致AVL树失衡,"根的左子树的高度"比"根的右子树的高度"大2。针对该情况,我们需要进行单右旋转来完成对树的调整。

18663315d88b232c208f187cab8851d2.png

图中左边是旋转之前的树,右边是旋转之后的树。从中可以发现,旋转之后的树又变成了AVL树,而且该旋转只需要一次即可完成。

对于LL旋转,你可以这样理解为:LL旋转是围绕"失去平衡的AVL根节点"进行的,也就是节点4;而且由于是LL情况,就将节点4进行一次顺时针旋转。

代码实现:

/**

* 进行一次单右旋转

*

* @param node 最小失衡树根节点

*/

private AVLTreeNode rightRotation(AVLTreeNode node) {

AVLTreeNode left = node.left;

node.left = left.right;

left.right = node;

// 更新高度

node.height = Math.max(height(node.left), height(node.right)) + 1;

left.height = Math.max(height(left.left), height(left.right)) + 1;

return left;

}

3.2 RR旋转

在右子树插入右孩子导致AVL失衡时,我们需要进行单左旋调整。旋转围绕最小失衡子树的根节点进行。

3d337023dc1781d5e34914670e1555c6.png

/**

* 进行一次单左旋转

*

* @param node 最小失衡树根节点

*/

private AVLTreeNode leftRotation(AVLTreeNode node) {

AVLTreeNode right = node.right;

node.right = right.left;

right.left = node;

// 更新高度

node.height = Math.max(height(node.left), height(node.right)) + 1;

right.height = Math.max(height(right.left), height(right.right)) + 1;

return right;

}

3.3 RL旋转

“在右子树上插入左孩子导致AVL树失衡",此时我们需要进行先右旋后左旋的调整。

30bdf8d7158b6ddcb86c353255c8dc97.png

/**

* 先右旋后左旋

*

* @param node 失衡树根节点

* @return 旋转后的根节点

*/

private AVLTreeNode rightLeftRotation(AVLTreeNode node) {

node.right = rightRoation(node.right);

return leftRoation(node);

}

3.4 LR旋转

“在左子树上插入右孩子导致AVL树失衡",此时我们需要进行先左旋后右旋的调整。

119e243837312557d89fe030ffe46961.png

/**

* 先左旋后右旋

*

* @param node 失衡树根节点

* @return 旋转后的根节点

*/

private AVLTreeNode leftRightRotation(AVLTreeNode node) {

node.left = leftRoation(node.left);

return rightLeftRoation(node);

}

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[【数据结构】什么是AVL树]http://www.zyiz.net/tech/detail-91777.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值