前言
大家都玩过球球大作战的游戏吧,他的原型是Agar.IO,在这款游戏了我们扮演一个小球,刚出生的我们除了速度快,视野生存能力都一般,为了追求某种平衡,通过不断的吞噬其他小球来让自己变大,变长,但是我们的速度却在下降.这个追逐平衡的过程呢,就是我们今天的主题,AVL树,AVL树也叫二叉平衡树,是一种二叉排序树,其中每一个节点的左子树和右子树高度差至多等于1.这样做的好处是,我们的查找会非常方便,而且也避免了二叉树变成斜树而带来的性能影响.
二叉平衡树的实现原理
在AVL树中,每当我们插入一个节点,就检查是否因为插入而破坏了树的平衡,如果破话了平衡,就找出最小不平衡树(距离插入节点最近的,平衡因子大于1的节点为根的子树),在保持AVL树特性的前提下,进行旋转操作,来达到平衡.那么破坏平衡的插入是哪4个呢?
插入节点左子树的左子树 LL
插入节点左子树的右子树 LR
插入节点右子树的左子树 RL
插入节点右子树的右子树 RR
那么对于这四种情况,我们分别要用到这些旋转操作,比如LL要用
//LL旋转 public static Node rotateWidthLeftChild(Node tree){ Node root=tree.leftChild; tree.leftChild=root.rightChild; root.rightChild=tree; tree.height=Math.max(height(tree.leftChild), height(tree.rightChild))+1; root.height=Math.max(height(root.leftChild), tree.height)+1; return root; }
LR要用
//LR public static Node doubleWidthLeftChild(Node tree){ tree.leftChild=rotateWidthRightChild(tree.leftChild); return rotateWidthLeftChild(tree); }
RR要用
//RR旋转 public static Node rotateWidthRightChild(Node tree){ Node root=tree.rightChild; tree.rightChild=root.leftChild; root.leftChild=tree; tree.height=Math.max(height(tree.leftChild), height(tree.rightChild))+1; root.height=Math.max(height(root.leftChild), tree.height)+1; return root; }
RL要用
//RL public static Node doubleWidthRightChild(Node tree){ tree.rightChild=rotateWidthLeftChild(tree.rightChild); return rotateWidthRightChild(tree); }