摘要
AVL即二叉查找树相对红黑树作为一种面对低频修改,大量查询的数据结构。网上已有比较成熟的实现方式,但是在读到本章节浏览网上实现过程发现大都侧重逻辑实现读起来通常都有点佶屈聱牙的感觉。为了梳理逻辑并且本着打造一个更好的轮子的天真想法写下了此文。各位轻拍
AVL TREE定义
AVL书是一种平衡二叉查找树,所以遵循平衡二叉树的一些性质:
树的左右高度差不能超过1
任何网下递归的左子树和右子书必须符合第一条性质
没有任何节点的空树或只有根节点的树也是平衡二叉树
而AVL则是苏联数学家Adelson-Velsky和Landis命名的平衡二叉树算法,通过不断旋转达到树的平衡
AVL TREE核心概念
旋转(以右旋为例左旋亦然)
关于旋转有几种说法:
所谓右旋《码出高效》说法是是以一某个节点为中心,将它沉入当前右子节点的位置也称顺时针旋转。
对于LL旋转,你可以这样理解为:LL旋转是围绕"失去平衡的AVL根节点"进行的,也就是节点k2;而且由于是LL情况,即左左情况,就用手抓着"左孩子,即k1"使劲摇。将k1变成根节点,k2变成k1的右子树,"k1的右子树"变成"k2的左子树"。
个人觉得网友网友skywang12345说法更加直观一点,其LL旋转即为右旋。但是其将旋转根据失衡状态分为四种旋转个人不甚赞同,直接按照失衡区感觉有些增加了记忆复杂度并且切断了失衡恢复中的一些联系。其实旋转只有左旋右旋两种所谓重旋转只是左旋和右旋的不同组合而已。
需要注意的两点是1.对node节点右旋是以node节点的左子节点为旋转中心的,在一个是旋转完成后的新根节变成了旋转中心左子节点,而node节点成为了新根节点的右子节点,原来左子节点的右子节点(下图节点6)变为node的左子节点。具体可见图示:
以4为中心旋转失衡的集中情况及其对应旋转
如下图所示AVL TREE失衡主要是分为四种情况: LL、LR、RL、RR,所谓LL即由于新的节点插入到了左子树(L)的左子树(L)得名,同理LR可以理解为新的节点插入到左子树(L)的右子树(R)得名,RL,RR亦然。不同失衡状态的恢复对应旋转:
LL R旋(root)
4为中心LRL旋(root.left)=>R旋(root)
RL=>R旋(root.right)=>L旋(root)
RR=>L旋(root)
Java实现:
本文的实现思路基本参照文章:https://www.cnblogs.com/skywang12345/p/3577479.html, 对其中旋转部分抽象和重命名提高了可读性github地址:https://github.com/dongyuelsqm/AVL-TREE.git
主要步骤 失衡状态和旋转方式绑定在NodeStatusEnum中参考:
https://www.cnblogs.com/skywang12345/p/3577479.html
《码出高效》
网友评论