AVL Tree - AVL二叉树


特性

AVL树是最早发明的一种自平衡二叉查找树,树中的任何节点的左右两个子树的高度最大差别为,因此也称为高度平衡树。包含个节点的AVL树其查找、插入、删除操作的平均时间复杂度都是。AVL树高度为

引入二叉树上节点之间距离和高度的定义。一个叶子节点向上到达根节点所经过的跳数为这两个节点的距离,一个节点和自己的距离为,将空节点的高度视作。根节点到达其所有叶子节点的最大距离即为根节点的高度,同时也是该子树的高度。显然对于任意节点都有

一个节点的左右孩子的高度差为该节点的平衡因子

当一个节点的时称该节点所在的子树是平衡的,否则是不平衡的。

除了基本的二叉查找树属性,AVL树拥有以下属性:

AVL树上所有节点都是平衡的,即平衡性;

AVL树的高度为根节点的高度;

AVL树的高度为

旋转操作

AVL树的查询操作和二叉查找树一样,插入/删除操作也基本相同,首先通过二分查找找到合适插入的位置/要被删除的节点,然后做插入/删除操作。插入/删除会破坏AVL树的平衡性,LL(单向右旋平衡处理/左左)、RR(单向左旋平衡处理/右右)、LR(先左后右双向旋转平衡处理/左右)、RL(先右后左双向旋转平衡处理/右左)四种情况是所有需要调整的情况:

AVLTree1.png

AVLTree2.png

AVLTree3.png

AVLTree4.png

上面四种情况包含了所有从不平衡转化为平衡。通过节点的高度值、该节点是其父结点的左或者右,可以判断节点属于哪种情况,做相应的操作。

插入

对于下面这个AVL树,每个节点中上面的数字是节点下标,下面的数字是该节点的高度值。将从该AVL树的根节点开始,按照二分查找算法依次经过节点,最后插入的右孩子节点;

AVLTree5.png

新节点插入完成后,我们沿着父结点指针一路向上,检查每个节点是否平衡,若不平衡则进行旋转操作,再更新节点高度,直到根节点。

AVLTree6.png

节点为叶子节点,因此高度值为

AVLTree7.png

平衡因子为,不需要旋转,更新节点的高度值

AVLTree8.png

AVLTree9.png

平衡因子为,需要进行RR操作,旋转后节点的高度值为,更新节点的高度值

AVLTree10.png

平衡因子为,更新节点的高度值

AVLTree11.png

平衡因子为,更新节点的高度值

AVLTree12.png

平衡因子为,更新节点的高度值

删除

AVL树的删除操作和BinarySearchTree一样:

为叶子节点,既没有左孩子节点也没有右孩子节点,直接删除;

只有一个孩子节点,则像链表一样将从其父节点和之间删除;

同时有左右孩子节点,按照中序遍历找出二叉树中比大的下一个节点(中序遍历下的后继节点),用其值代替,再继续用相同的规则递归的删除原始节点(实际上,中序遍历的后继节点不可能存在左孩子节点,要么无孩子节点,要么只有右孩子节点);

删除完成后从的父节点开始依次向上,检查每个节点是否平衡,若不平衡则进行旋转操作,再更新节点高度,直到根节点。检查本身的时间复杂度为。下图中删除节点,节点的中序遍历后继节点代替它,然后删除真正的。从新的开始检查每个节点是否平衡,直到根节点。本次删除结束。

AVL树的插入/删除操作的实际操作需要约次,其中花费在从根节点向下寻找合适的插入位置/要被删除的节点,花费在插入/删除完成后向上对每个节点的检查以及旋转操作。

AVLTree13.png


AVL Tree


源码

AvlTree.h

AvlTree.cpp

测试

AvlTreeTest.cpp