1.增删一个节点导致不平衡的说明该节点的父节点只有这个节点一个孩子
2.二叉平衡树的height属性不能直接取,因为该节点可能为空,所以要必须通过height()方法取,在里面对空指针进行判断
3.在作用于树时,递归是一直进入到退出条件(一般是底层结构)才 开始逐步退出递归,是自底向上,类似于中序遍历,而递归则是从根节点就开始一路访问下去,类似于先序。因此当需重新建立父子之间的关系时,循环是声明一个指向当前节点和其父节点的应用来实现,而递归则是等到退出递归时返回子节点再处理与父节点的关系
4.不平衡是增删节点后某个节点的左右子树的高度差等于2,而却增删节点导致的是该节点所在的部分失衡,因此退出递归后检查该节点左右子树的高度差,从而确定失衡的部分
其他看下面的代码注释
/** * Created by 刘逗逼 on 2016/2/26. */ public class AVLTree<T extends Comparable<T>> { private AVLNode<T> root=null; public class AVLNode<T>{ private int height; private T key; private AVLNode<T> left; private AVLNode<T> right; public AVLNode(T key,AVLNode<T> left,AVLNode<T> right){ this.key=key; this.left=left; this.right=right; this.height=0; } } public AVLTree(){ root=null; } public int height(AVLNode<T> tree){ if(tree!=null)return tree.height; return 0; } public int height(){ return height(root); } public int max(int a,int b){ return a>b?a:b; } public void preOrder(AVLNode<T> tree){ if(tree!=null){ System.out.println("the key is "+tree.key); preOrder(tree.left); preOrder(tree.right); } } public void preOrder(){ preOrder(root); } public void inOrder(AVLNode<T> tree){ if(tree!=null){ inOrder(tree.left); System.out.println("the key is "+tree.key); inOrder(tree.right); } } public void inOrder(){ inOrder(root); } public void postOrder(AVLNode<T> tree){ if(tree!=null){ postOrder(tree.left); postOrder(tree.right); System.out.println("the key is "+tree.key); } } public void postOrder(){ postOrder(root); } //(递归实现)查找AVL树tree中键值为key的节点 public AVLNode<T> search(AVLNode<T> tree,T key){ if(tree==null){ return null; } int cmp=key.compareTo(tree.key); if(cmp<0){ return search(tree.left,key); //往左子树寻找 }else if(cmp>0){ return search(tree.right,key); }else { return tree; } } public AVLNode<T> search(T key){ if(root==null){ return null; }else { return search(root,key); } } //(非递归实现)查找AVL树tree中键值为key的节点 public AVLNode<T> iterativeSearch(AVLNode<T> tree,T key) { while (tree!=null){ int cmp=key.compareTo(tree.key); if(cmp<0){ tree=tree.left; }else if(cmp>0){ tree=tree.right; }else return tree; } return tree; } //查找最小结点:返回tree为根结点的AVL树的最小结点 public AVLNode<T> minimum(AVLNode<T> tree){ if(tree==null){ return null; } while (tree.left!=null){ tree=tree.left; } return tree; } public AVLNode<T> minimum(){ return minimum(root); } //查找最大结点:返回tree为根结点的AVL树的最大结点。 public AVLNode<T> maximum(AVLNode tree){ if(tree==null){ return null; } while (tree.right!=null){ tree=tree.right; } return tree; } public AVLNode<T> maximum(){ return minimum(root); } //LL:左左对应的情况(左单旋转)。 public AVLNode<T> leftLeftRotation(AVLNode<T> k2){ AVLNode<T> k1=k2.left; k2.left=k1.right; k1.right=k2; k2.height=max(height(k2.left),height(k2.right))+1; k1.height=max(height(k1.left),height(k2))+1; return k1; } //RR:右右对应的情况(右单旋转)。 public AVLNode<T> rightRightRotation(AVLNode<T> k2){ AVLNode<T> k1=k2.right; k2.right=k1.left; //k1.left存在时便是已过去,不存在也无所谓 k1.left=k2; k1.height=max(height(k1.right),height(k2))+1; k2.height=max(height(k2.left),height(k2.right))+1; return k1; } //LR:左右对应的情况(左双旋转)。 先RR再LL public AVLNode<T> leftRightRotation(AVLNode<T> k1){ AVLNode<T> k2=k1.left; AVLNode<T> k3=k2.right; rightRightRotation(k2); return leftLeftRotation(k1); } //RL:右左对应的情况(右双旋转)。 先LL再RR public AVLNode<T> rightLeftRotation(AVLNode<T> k1){ AVLNode<T> k2=k1.right; AVLNode<T> k3=k2.left; leftLeftRotation(k2); return rightRightRotation(k1); } // 将结点插入到AVL树中,,并返回根节点 //因为有返回根节点,因此找到位置后只需直接生成节点然后退出递归时完成父子节点之间的连接 public AVLNode<T> insert(AVLNode<T> tree,T key){ if(tree==null){ AVLNode<T> node=new AVLNode<T>(key,null,null); if(root==null){ //空树 root=node; return root; } return node; }else { int cmp=key.compareTo(tree.key); if(cmp<0){ tree.left=insert(tree.left,key); if(height(tree.left)-height(tree.right)==2) { if ((key.compareTo(tree.left.key)) < 0) { //LL return leftLeftRotation(tree.left); } else { return leftRightRotation(tree.left); //LR } } }else if(cmp>0){ tree.right=insert(tree.right,key); if(height(tree.right)-height(tree.left)==2){ if((key.compareTo(tree.right.key)<0)){ return rightLeftRotation(tree.right); //RL }else { return rightRightRotation(tree.right); //RR } } }else{ //cmp==0 System.out.println("添加失败:不允许添加相同的节点!"); } } tree.height=max(height(tree.left),height(tree.right))+1; //LL之类中对height的调整只是对那部分的而已 //之上的节点也要递归改变节点的height return tree; } public AVLNode<T> insert(T key){ return insert(root,key); } //删除结点node,返回根节点 public AVLNode<T> remove(AVLNode<T> tree,AVLNode<T> node){ // 根为空 或者 没有要删除的节点,直接返回null。 if(tree==null||node==null){ return null; } int cmp=node.key.compareTo(tree.key); if(cmp<0){ //要被删除的节点在左子树 tree.left=remove(tree.left,node); //在删除了节点跳出递归时,此时相当于把被删除节点的父节点 //的左孩子置空 if(height(tree.right)-height(tree.left)==2){ //不平衡 AVLNode<T> r=tree.right; //删除节点要平衡的是另外一边 if(r.left.height>r.right.height){ // RL return rightLeftRotation(tree); }else return rightRightRotation(tree); // RR } }else if(cmp>0){ tree.right=remove(tree.right,node); if(height(tree.left)-height(tree.right)==2) { AVLNode<T> l = tree.left; if (height(l.left) > height(l.right)) { return leftLeftRotation(tree); //LL } else return leftRightRotation(tree); //LR } }else { //cmp==0,删除该节点(与二叉查找树的删除相同) if (tree.left != null && tree.right != null) { //如果两个孩子不为空的话 //二叉查找树中替代被删除节点的可以是前继或者后继,但这里为了保持平衡,取高度高的那边 if (height(tree.left)< height(tree.right)) { AVLNode<T> replace = minimum(tree.right); //后继节点 tree.key = replace.key; return remove(tree.right, replace); } else { AVLNode<T> replace = maximum(tree.left); tree.key = replace.key; return remove(tree.left, replace); } }else { AVLNode<T> tmp=tree; tree=(tree.left!=null)?tree.left:tree.right; //之后通过返回来把上一层的子节点给确定 tmp=null; } } tree.height=max(height(tree.left),height(tree.right))+1;//退出递归时,处理手尾 return tree; } public void remove(T key) { AVLNode<T> z; if ((z = search(root, key)) != null) root = remove(root, z); } //销毁AVL树 public void destroy(AVLNode<T> tree){ if(tree==null){ return ; } destroy(tree.left); destroy(tree.right); tree=null; } public void destroy(){ destroy(root); } /* * 打印"二叉查找树" * * key -- 节点的键值 * direction -- 0,表示该节点是根节点; * -1,表示该节点是它的父结点的左孩子; * 1,表示该节点是它的父结点的右孩子。 */ public void print(AVLNode<T> tree,T key,int direction){ //把父节点的信息带入下一层 if(tree!=null){ if(tree!=null){ //先序打印 if(direction==0){ System.out.println(tree.key+" is root"); }else { String relationship=direction==1?"right child":"left child"; System.out.println(tree.key+" is "+key+"`s "+relationship); } print(tree.left,tree.key,-1); print(tree.right,tree.key,1); } } } public void print(){ if(root!=null){ print(root,root.key,0); } } }
纯粹地读书,只为好奇心