My集合框架第三弹 AVL树
旋转操作:
由于任意一个结点最多只有两个儿子,所以当高度不平衡时,只可能是以下四种情况造成的:
1. 对该结点的左儿子的左子树进行了一次插入。
2. 对该结点的左儿子的右子树进行了一次插入。
3. 对该结点的右儿子的左子树进行了一次插入。
4. 对该结点的右儿子的右子树进行了一次插入。
向AVL树插入节点后,需要让AVL树重新平衡
step1:从插入节点向根节点溯源,观察是否存在不平衡节点(左右子树高度差),
if(不存在),return
else step2
step2:标记不平衡节点为K1
if(K1.left.depth>K1.right.depth) step3;
else step4;
step3:根据插入值和K2元素值比较
if(K3<K2.element) 情形1;
else 情形2;
step4:if(K3<K2.element) 情形3;
else 情形4;
情形1:
K1为不平衡节点,K3为插入节点
经过一次单旋转,变为
代码实现
public AvlNode<AnyType> rotateWithLeftChild(AvlNode<AnyType> K1){ AvlNode<AnyType> K2 = K1.left; K1.left = K2.right; K2.right = K1; //更新高度(省略) return K2; }
注意:一定要更新父节点的左子树的指向
情形4与情形1对称,不在赘述
情形2:对应于左右双旋
为了描述清楚,即使树中的节点为null,仍然标记为字母ABCD
K1为不平衡节点
step1:K2
以K2为不平衡节点左旋,得到
继续以K1为不平衡节点右旋,得到平衡
代码:
public AvlNode<AnyType> doubleWithLeftChild(AvlNode<AnyType> K1){ K1.left = rotateWithRightChild(K1.left); return rotateWithLeftChild(K1); }
情形3与之对称
部分代码如下:
package com.wpr.collection; public class AVLTree<AnyType extends Comparable<? super AnyType>> { private static class AVLNode<AnyType> { AnyType element; AVLNode<AnyType> left; AVLNode<AnyType> right; int height; public AVLNode(AnyType element) { this(element,null,null); } public AVLNode(AnyType element2,AVLNode<AnyType> left, AVLNode<AnyType> right) { this.element = element2; this.left = left; this.right = right; } } AVLNode<AnyType> root; public void insert(AnyType x){ if(x!=null) root = insert(x,root); } private AVLNode<AnyType> insert(AnyType x,AVLNode<AnyType> t){ if(t==null) return new AVLNode<AnyType>(x); int compareResult = x.compareTo(t.element); if(compareResult<0){ //在左子树上插入 t.left = insert(x,t.left); if(height(t.left)-height(t.right)==2){ //存在不平衡节点t if(x.compareTo(t.left.element)<0) //情形一 t = rotateWithLeftChild(t); else //情形二 t = doubleWithLeftChild(t); } }else if(compareResult>0){ t.right = insert(x,t.right); if(height(t.right)-height(t.left)==2){ //存在不平衡节点 if(x.compareTo(t.right.element)>0) //情形三 t = rotateWithRightChild(t); else //情形四 t = doubleWithRightChild(t); } } t.height = Math.max(height(t.left), height(t.right))+1; return t; } private AVLNode<AnyType> doubleWithRightChild(AVLNode<AnyType> t) { t.right = rotateWithLeftChild(t.right); return rotateWithRightChild(t); } private AVLNode<AnyType> rotateWithRightChild(AVLNode<AnyType> t) { AVLNode<AnyType> temp = t.right; t.right = temp.left; temp.left =t; t.height = Math.max(height(t.left), height(t.right))+1; temp.height = Math.max(height(temp.left), height(temp.right))+1; return temp; } private AVLNode<AnyType> doubleWithLeftChild(AVLNode<AnyType> t) { t.left = rotateWithRightChild(t.left); return rotateWithLeftChild(t); } private AVLNode<AnyType> rotateWithLeftChild(AVLNode<AnyType> t) { AVLNode<AnyType> temp = t.left; t.left = temp.right; temp.right = t; t.height = Math.max(height(t.left), height(t.right))+1; temp.height = Math.max(height(temp.left), height(temp.right))+1; return temp; } private int height(AVLNode<AnyType> t){ return t==null?-1:t.height; } /** * 打印树 */ public void printTree(){ if(isEmpty()){ System.out.println("Empty Tree"); } printTree(root); } /** * 中序遍历树 * @param t */ private void printTree(AVLNode<AnyType> t) { if(t!=null){ System.out.print(t.element+"\t"); printTree(t.left); printTree(t.right); } } public boolean isEmpty() { return root == null; } }
上面AVLNode记录的是树的高度,参考了别人的文章,可以改成平衡因子。。
http://blog.csdn.net/ljianhui/article/details/9137177
http://blog.csdn.net/ljianhui/article/details/9204667