树-二叉平衡树AVL

基本概念


AVL树:树中任何节点的两个子树的高度最大差别为1。

AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。

AVL实现


AVL树的节点包括的几个组成对象:
(01) key -- 是关键字,是用来对AVL树的节点进行排序的。
(02)
left -- 是左孩子。
(03) right -- 是右孩子。
(04) height --
是高度。即空的二叉树的高度是0,非空树的高度等于它的最大层次(根的层次为1,根的子节点为第2层,依次类推)。

AVL旋转算法

AVL失衡四种形态:

LL(根的左子树的左子树高):根节点的左子树的左子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2。

LR(根的左子树的右子树高):根节点的左子树的右子树还有非空子节点,导致"根的左子树的高度"比"根的右子树的高度"大2。

RL(根的右子树的左子树高):根节点的右子树的左子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2。

RR(根的右子树的右子树高):根节点的右子树的右子树还有非空子节点,导致"根的右子树的高度"比"根的左子树的高度"大2。

旋转算法实现


1 LL(一步到位)

LL失去平衡的情况,可以通过一次旋转让AVL树恢复平衡。如下图:

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

对于LL旋转,你可以这样理解为:LL旋转是围绕"失去平衡的AVL根节点"进行的,也就是节点k2;而且由于是LL情况,即左左情况,就用手抓着"左孩子,即k1"使劲摇。将k1变成根节点,k2变成k1的右子树,"k1的右子树"变成"k2的左子树"。

/*
* LL:左左对应的情况(左单旋转)。
*
* 返回值:旋转后的根节点
*/

static Node* left_left_rotation(AVLTree k2)
{

    AVLTree 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(一步到位)

理解了LL之后,RR就相当容易理解了。RR是与LL对称的情况!RR恢复平衡的旋转方法如下:

图中左边是旋转之前的树,右边是旋转之后的树。RR旋转也只需要一次即可完成。

/*
* RR:右右对应的情况(右单旋转)。
*
* 返回值:旋转后的根节点

*/
static Node* right_right_rotation(AVLTree k1)
{

    AVLTree 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(两步旋转RR->LL)

LR失去平衡的情况,需要经过两次旋转才能让AVL树恢复平衡。如下图:


第一次旋转是围绕"k1"进行的"RR旋转",第二次是围绕"k3"进行的"LL旋转"。

/*
* LR:左右对应的情况(左双旋转)。
*
* 返回值:旋转后的根节点

*/
static Node* left_right_rotation(AVLTree k3)
{

    k3->left = right_right_rotation(k3->left);

return left_left_rotation(k3);
}


4 RL(两步旋转LL->RR)

RL是与LR的对称情况!RL恢复平衡的旋转方法如下:

第一次旋转是围绕"k3"进行的"LL旋转",第二次是围绕"k1"进行的"RR旋转"。

/*
* RL:右左对应的情况(右双旋转)。
*
* 返回值:旋转后的根节点

*/
static Node* right_left_rotation(AVLTree k1)
{

    k1->right = left_left_rotation(k1->right);

return right_right_rotation(k1);
}


AVL操作


插入

步骤1:递归插入到左子树或右子树(left<root<right);

步骤2:比较左右子树高度来确定AVL失衡处理类型:

插入到左子树,就有LL和LR:通过left<root<right确定;

插入到右子树,就有RL和RR:通过left<root<right确定;

步骤3:修正树高。

删除

时间: 2024-11-03 05:16:43

树-二叉平衡树AVL的相关文章

二叉树--二叉平衡树

二叉平衡树是二叉树中最为最要的概念之一,也是在语言库或者项目中应用比较广泛的一种特殊的树形结构. 二叉平衡树 AVL树是高度平衡的而二叉树.它的特点是:AVL树中任何节点的两个子树的高度最大差别为1. 通常AVL树是在二叉搜索树上,经过局部调整而建立的,因此,它还是一棵排序树. 上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都<=1:而右边的不是AVL树,因为7的两颗子树的高度相差为2(以2为根节点的树的高度是3,而以8为根节点的树的高度是1). 性质 左右子树相差不超过1.

java项目---用java实现二叉平衡树(AVL树)并打印结果(详)

1 package Demo; 2 3 public class AVLtree { 4 private Node root; //首先定义根节点 5 6 private static class Node{ //定义Node指针参数 7 private int key; //节点 8 private int balance; //平衡值 9 private int height; //树的高度 10 private Node left; //左节点 11 private Node right;

二叉平衡树的插入和删除操作

1.      二叉平衡树 二叉排序树的时间复杂度和树的深度n有关.当先后插入的结点按关键字有序时,二叉排序树退化为单枝树,平均查找长度为(n+1)/2,查找效率比较低.提高查找效率,关键在于最大限度地降低树的深度n.因此需要在构成二叉排序树的过程中进行“平衡化”处理,使之成为二叉平衡树. 二叉平衡树,又称AVL树.它或者是一棵空树,或者是具有下列性质的树: 1)      具备二叉排序树的所有性质: 2)      左子树和右子树深度差的绝对值不超过1: 3)      左子树和右子树都是二叉

二叉平衡树之删除节点

二叉平衡树之删除节点操作 更好的判断最小非平衡树类型的方法 在前一篇文章中,我们知道最小非平衡树可以分为四种类型,即:LL型.LR型.RR型和RL型.而且我也按照自己的理解,归纳了判断是哪种类型的方法.总结一下就是:设最小非平衡树的树根为unbalance,首先看unbalance的左右子树谁更高,如果左子树更高则为LX型.如果是右子树高则为RX型.再进一步,如果为LX型,将刚刚插入的节点的值value与unbalance左孩子进行比较,如果value大则为LR型,如果value小则为LL型.如

二叉树遍历的应用(路径和问题,判断是否是二叉搜索树,判断是否是二叉平衡树)

现在越发觉得关于树的问题真是千变万化,随便改一个条件又会是一个新的问题. 先序遍历求二叉树路径问题 问题:一棵二叉树每个节点包含一个整数,请设计一个算法输出所有满足条件的路径:此路径上所有节点之和等于给定值.注意此类路径不要求必须从根节点开始. 如果没有最后一个条件,这道题在leetcode上面见过,就是采取先序遍历的方式并记录下路径.但是加上最后一个条件后需要转下弯思考一下. 当然也需要记录下路径,并且记得要回溯.加上不要求从根节点开始这个条件后可以这么思考,每次遍历到当前节点时,从路径中查找

判断一颗二叉树是否为二叉平衡树 python 代码

输入一颗二叉树,判断这棵树是否为二叉平衡树.首先来看一下二叉平衡树的概念:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.因此判断一颗二叉平衡树的关键在于求出左右子树的高度差,而二叉树的高度又是怎么定义的呢?二叉树的高度指的是从根节点到叶子节点所有路径上包含节点个数的最大值.所以我们可以得出,父亲节点的高度与左右子树高度的关系为:父亲节点的高度=max(左子树高度,右子树高度)+1,同时我们知道,叶子节点的高度值为1(或则0,这里定义1或者0对判断结

数据结构与算法问题 AVL二叉平衡树

AVL树本质上还是一棵二叉搜索树,它的特点是: 本身首先是一棵二叉搜索树. 带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子)最多为1 #include <iostream> using namespace std; const int LH = 1; const int EH = 0; const int RH = -1; bool TRUE = 1; bool FALSE = 0; typedef struct BSTNode { int key; int bf; BSTNod

平衡二叉搜索树(AVL树,红黑树)数据结构和区别

平衡二叉搜索树(Balanced Binary Search Tree) 经典常见的自平衡的二叉搜索树(Self-balancing Binary Search Tree)有 ① AVL树 :Windows NT 内核中广泛使用 ② 红黑树:C++ STL(比如 map.set )Java 的 TreeMap.TreeSet.HashMap.HashSet  Linux 的进程调度  Ngix 的 timer 管理 1 AVL树  vs  红黑树 ①AVL树 平衡标准比较严格:每个左右子树的高度

伸展树 - 二叉搜索树的扩展2

目录 伸展树的介绍 伸展树的C实现 1 节点定义 2 旋转 3 伸展树的伸展 4 搜索 4 伸展树的插入和删除 全部代码和参考资料 1. 伸展树的介绍 伸展树(splay tree)是一种搜索二叉树,它能在O(log n)内完成插入.查找和删除操作. (1)伸展树满足搜索二叉树的性质,左子节点小于根节点,右子节点大于等于根节点. (2)伸展树独有特点:当某个节点被访问时,伸展树会通过旋转使该节点成为树的根. 伸展树的出发点是这样的:考虑到局部性原理(刚被访问的内容下次更大的可能仍会被访问)和二八