AVL Tree - AVL二叉树
特性
AVL树是最早发明的一种自平衡二叉查找树,树中的任何节点的左右两个子树的高度最大差别为,因此也称为高度平衡树。包含个节点的AVL树其查找、插入、删除操作的平均时间复杂度都是。AVL树高度为。
引入二叉树上节点之间距离和高度的定义。一个叶子节点向上到达根节点所经过的跳数为这两个节点的距离,一个节点和自己的距离为,将空节点的高度视作。根节点到达其所有叶子节点的最大距离即为根节点的高度,同时也是该子树的高度。显然对于任意节点都有
一个节点的左右孩子的高度差为该节点的平衡因子
当一个节点的时称该节点所在的子树是平衡的,否则是不平衡的。
除了基本的二叉查找树属性,AVL树拥有以下属性:
AVL树上所有节点都是平衡的,即平衡性;
AVL树的高度为根节点的高度;
AVL树的高度为;
旋转操作
AVL树的查询操作和二叉查找树一样,插入/删除操作也基本相同,首先通过二分查找找到合适插入的位置/要被删除的节点,然后做插入/删除操作。插入/删除会破坏AVL树的平衡性,LL(单向右旋平衡处理/左左)、RR(单向左旋平衡处理/右右)、LR(先左后右双向旋转平衡处理/左右)、RL(先右后左双向旋转平衡处理/右左)四种情况是所有需要调整的情况:
上面四种情况包含了所有从不平衡转化为平衡。通过节点的高度值、该节点是其父结点的左或者右,可以判断节点属于哪种情况,做相应的操作。
插入
对于下面这个AVL树,每个节点中上面的数字是节点下标,下面的数字是该节点的高度值。将从该AVL树的根节点开始,按照二分查找算法依次经过节点,最后插入的右孩子节点;
新节点插入完成后,我们沿着父结点指针一路向上,检查每个节点是否平衡,若不平衡则进行旋转操作,再更新节点高度,直到根节点。
节点为叶子节点,因此高度值为;
平衡因子为,不需要旋转,更新节点的高度值;
平衡因子为,需要进行RR操作,旋转后节点的高度值为,更新节点的高度值;
平衡因子为,更新节点的高度值;
平衡因子为,更新节点的高度值;
平衡因子为,更新节点的高度值;
删除
AVL树的删除操作和BinarySearchTree一样:
若为叶子节点,既没有左孩子节点也没有右孩子节点,直接删除;
若只有一个孩子节点,则像链表一样将从其父节点和之间删除;
若同时有左右孩子节点,按照中序遍历找出二叉树中比大的下一个节点(中序遍历下的后继节点),用其值代替,再继续用相同的规则递归的删除原始节点(实际上,中序遍历的后继节点不可能存在左孩子节点,要么无孩子节点,要么只有右孩子节点);
删除完成后从的父节点开始依次向上,检查每个节点是否平衡,若不平衡则进行旋转操作,再更新节点高度,直到根节点。检查本身的时间复杂度为。下图中删除节点,节点的中序遍历后继节点代替它,然后删除真正的。从新的开始检查每个节点是否平衡,直到根节点。本次删除结束。
AVL树的插入/删除操作的实际操作需要约次,其中花费在从根节点向下寻找合适的插入位置/要被删除的节点,花费在插入/删除完成后向上对每个节点的检查以及旋转操作。
AVL Tree
- https://www.geeksforgeeks.org/avl-tree-set-1-insertion/
- https://www.geeksforgeeks.org/avl-tree-set-2-deletion/