【数据结构与算法】平衡二叉树

AVL树简介

AVL树的名字来源于发明作者G.M. Adelson-Velsky 和 E.M. Landis的缩写。AVL树是最先发明的自平衡二叉查找树(Self-Balancing Binary Search Tree,简称平衡二叉树)。

平衡二叉树定义(AVL):它或者是一颗空树,或者具有以下性质的二叉排序树:它的左子树和右子树的深度之差(平衡因子)的绝对值不超过1,且它的左子树和右子树都是一颗平衡二叉树。一棵AVL树有如下必要条件:

  1. 条件一:它必须是二叉查找树。
  2. 条件二:每个节点的左子树和右子树的高度差至多为1。

图一中左边二叉树的节点45的左孩子46比45大,不满足二叉搜索树的条件,因此它也不是一棵平衡二叉树。
右边二叉树满足二叉搜索树的条件,同时它满足条件二,因此它是一棵平衡二叉树。

 

平衡因子:可通过计算非叶子结点的平衡因子来判断该树是否为平衡二叉树(叶子节点的平衡因子均为0)。

平衡因子 = 左子树高度 - 右子树高度

平衡因子 = 右子树高度 - 左子树高度

下图为每个节点的平衡因子:

  • 节点25的左子树高度为3,右子树高度为3,BF= 3- 3 = 1;
  • 节点20的左子树高度为2,右子树高度为1,BF= 2-1 = 1;
  • 节点36的左子树高度为2,右子树高度为2,BF= 2 - 2 = 0;
  • 节点30的左子树高度为1,右子树高度为0,BF= 1 - 0 =  1;

对于平衡二叉树,BF的取值范围为[-1,1]。如果发现某个节点的BF值不在此范围,则需要对树进行调整。

 

AVL树的平衡调整

整个实现过程是通过在一棵平衡二叉树中依次插入元素(按照二叉排序树的方式),若出现不平衡,则要根据新插入的结点与最低不平衡结点的位置关系进行相应的调整。分为LL型、RR型、LR型和RL型4种类型,各调整方法如下(下面用A表示最低不平衡结点):

左旋和右旋示意图:

 

case1: 左旋

由于在A的右孩子(R)的右子树(R)上插入新结点,使原来平衡二叉树变得不平衡,此时A的平衡因子由-1变为-2。图3是RR型的最简单形式。显然,按照大小关系,结点B应作为新的根结点,其余两个节点分别作为左右孩子节点才能平衡,A结点就好像是绕结点B逆时针旋转一样。

RR型调整(左旋)的一般形式如下图所示,表示在A的右孩子B的右子树BR(不一定为空)中插入结点(图中阴影部分所示)而导致不平衡( h 表示子树的深度)。这种情况调整如下:

  • 将A的右孩子B提升为新的根结点;
  • 将原来的根结点A降为B的左孩子;
  • 各子树按大小关系连接(AL和BR不变,BL调整为A的右子树)。

RR型调整例子如下:

 

 

case2:右旋

由于在A的左孩子(L)的左子树(L)上插入新结点,使原来平衡二叉树变得不平衡,此时A的平衡因子由1增至2。下面图1是LL型的最简单形式。显然,按照大小关系,结点B应作为新的根结点,其余两个节点分别作为左右孩子节点才能平衡,A结点就好像是绕结点B顺时针旋转一样。

LL型调整(右旋)的一般形式如图所示,表示在A的左孩子B的左子树BL (不一定为空) 中插入结点(图中阴影部分所示)而导致不平衡( h 表示子树的深度)。调整如下:

  • 将A的左孩子B提升为新的根结点;
  • 将原来的根结点A降为B的右孩子;
  • 各子树按大小关系连接(BL和AR不变,BR调整为A的左子树)

LL型调整例子如下:

 

 

 

case3:左右旋转

由于在A的左孩子(L)的右子树(R)上插入新结点,使原来平衡二叉树变得不平衡,此时A的平衡因子由1变为2。图5是LR型的最简单形式。显然,按照大小关系,结点C应作为新的根结点,其余两个节点分别作为左右孩子节点才能平衡。

 

LR型调整的一般形式如下图所示,表示在A的左孩子B的右子树(根结点为C,不一定为空)中插入结点(图中两个阴影部分之一)而导致不平衡( h 表示子树的深度)。这种情况调整如下:

  • 将B的左孩子C提升为新的根结点;
  • 将原来的根结点A降为C的右孩子;
  • 各子树按大小关系连接(BL和AR不变,CL和CR分别调整为B的右子树和A的左子树)。

左右旋转例子如下:

 

 

case4:右左旋转

由于在A的右孩子(R)的左子树(L)上插入新结点,使原来平衡二叉树变得不平衡,此时A的平衡因子由-1变为-2。图7是RL型的最简单形式。显然,按照大小关系,结点C应作为新的根结点,其余两个节点分别作为左右孩子节点才能平衡。

RL型调整的一般形式如下图8所示,表示在A的右孩子B的左子树(根结点为C,不一定为空)中插入结点(图中两个阴影部分之一)而导致不平衡( h 表示子树的深度)。这种情况调整如下:①将B的左孩子C提升为新的根结点;②将原来的根结点A降为C的左孩子;③各子树按大小关系连接(AL和BR不变,CL和CR分别调整为A的右子树和B的左子树)。

右左旋转例子如下:

 

平衡二叉树实现的实例

选取一组数据分别为1,2,3,4,5,6,7,8总共8个结点来构造平衡二叉树。

参考文献

1. avl树思想及实现

2. AVL Tree Datastructure

 

posted @ 2023-03-25 17:18  苏格拉底的落泪  阅读(67)  评论(0编辑  收藏  举报