平衡二叉树Java语言实现

来源:互联网 发布:oracle数据库命令大全 编辑:程序博客网 时间:2024/05/16 12:07

作为二叉查找树的升级版,平衡二叉树(AVL-Tree)可以有效保障树的深度,防止因为插入操作的顺序和删除操作等导致二叉查找树左右过于不均衡,下面的代码也是书上的源码代码,稍微改动和增加了些。

内部节点AvlNode:

<span style="white-space:pre"></span>/** * Node of AVLTree * @author LQC * * @param <AnyType> element extends Comparable */private static class AvlNode<AnyType>{AnyType element;AvlNode lc;AvlNode rc;int height;AvlNode(AnyType x){this(x, null, null);}AvlNode(AnyType x, AvlNode _lc, AvlNode _rc){this.element = x;this.lc = _lc;this.rc = _rc;height = 0;}}

插入函数,

<span style="white-space:pre"></span>/** * Internal method to insert item to AVLTree * @param x item to insert * @param n the node that roots the subtree * @return root of the subtree */private AvlNode<AnyType> insert(AnyType x, AvlNode<AnyType> n){if(n == null)return new AvlNode(x, null, null);//insertint cr = x.compareTo(n.element);if(cr < 0){//insertn.lc = insert(x, n.lc);//need to balanceif(getHeight(n.lc) - getHeight(n.rc) == 2){if(x.compareTo((AnyType) n.lc.element) < 0)n = rotateWithLeftChildren(n);elsen = doubleRotateWithLeftChildren(n);}}else if(cr > 0){n.rc = insert(x, n.rc);if(getHeight(n.rc) - getHeight(n.lc) == 2){if(x.compareTo((AnyType) n.rc.element) > 0)n = rotateWithRightChildren(n);elsen = doubleRotateWithRightChildren(n);}}n.height = Math.max(getHeight(n.lc), getHeight(n.rc)) + 1;return n;}

删除函数,

        /** * Internal method to remove item from subtree  * @param x * @return */private AvlNode<AnyType> remove(AnyType x, AvlNode<AnyType> n){if(n == null)return n;int cr = x.compareTo(n.element);if(cr < 0){n.lc = remove(x, n.lc);if(getHeight(n.rc) - getHeight(n.lc) == 2){// need to balanceif(n.rc.lc == null)return rotateWithRightChildren(n);elsereturn doubleRotateWithRightChildren(n);}}else if(cr > 0){n.rc = remove(x, n.rc);if(getHeight(n.lc) - getHeight(n.rc) == 2){// need to balanceif(n.lc.rc == null){// roatatereturn rotateWithLeftChildren(n);}elsereturn doubleRotateWithLeftChildren(n);}}else{if(n.lc != null && n.rc != null){AnyType m = findMin(n.rc).element;n.element = m;n.rc = remove(m, n.rc);return n;}elsereturn n.lc == null ? n.rc : n.lc;}return n;}
平衡二叉树在执行插入和删除操作后,都要进行平衡操作,确保操作后的数仍然满足平衡二叉树的条件(左右子树高度相差不超过1),出现不平衡时大致可以分为四种情况。

1:左单旋。如注释中所示,K1的左子树过长,由于K3小于K2和K1,所以执行一次单旋操作即可

<span style="white-space:pre"></span>/** *    K1            K2 *    K2     ->    K3     K1 *  k3 * @param n * @return */private AvlNode<AnyType> rotateWithLeftChildren(AvlNode<AnyType> n){AvlNode<AnyType> k1 = n;AvlNode<AnyType> k2 = n.lc;AvlNode<AnyType> k3 = n.lc.lc;k1.lc = k2.rc;k2.rc = k1;//set heightk1.height = Math.max(getHeight(k1.lc), getHeight(k1.rc)) + 1;k2.height = Math.max(getHeight(k2.lc), getHeight(k2.rc)) + 1;return k2;}
2:左双旋。此时,左单旋不能解决问题,需要旋转两次,首先对K2进行左单旋,旋转之后变为第一种模式,因此对K1执行再一次左单选即可(代码如下another method)。也可以直接对K1,K2,K3的子树进行移动,代码如下所示。

<span style="white-space:pre"></span>/** *      K1             K3 *   K2       ->    K2     K1 *      K3 * @param n * @return */private AvlNode<AnyType> doubleRotateWithLeftChildren(AvlNode<AnyType> n){AvlNode<AnyType> k1 = n;AvlNode<AnyType> k2 = n.lc;AvlNode<AnyType> k3 = n.lc.rc;k2.rc = k3.lc;k1.lc = k3.rc;k3.lc = k2;k3.rc = k1;k1.height = Math.max(getHeight(k1.lc), getHeight(k1.rc)) + 1;k2.height = Math.max(getHeight(k2.lc), getHeight(k2.rc)) + 1;k3.height = Math.max(getHeight(k3.lc), getHeight(k3.rc)) + 1;// another method//k1.lc = rotateWithRightChildren(k2);//return rotateWithLeftChildren(k1);return k3;}
3:右单旋、右双旋和左单旋、左双旋是对称的,执行步骤基本类似,代码如下。

<span style="white-space:pre"></span>/** *     K1               K2 *        K2    ->    K1     K3 *          K3 * @param n * @return */private AvlNode<AnyType> rotateWithRightChildren(AvlNode<AnyType> n){AvlNode<AnyType> k1 = n;AvlNode<AnyType> k2 = n.rc;k1.rc = k2.lc;k2.lc = k1;k1.height = Math.max(getHeight(k1.lc), getHeight(k1.rc)) + 1;k2.height = Math.max(getHeight(k2.lc), getHeight(k2.rc)) + 1;return k2;}/** *     K1             K2 *        K3   ->  K1    K3 *     K2 * @param n * @return */private AvlNode<AnyType> doubleRotateWithRightChildren(AvlNode<AnyType> n){AvlNode<AnyType> k1 = n;AvlNode<AnyType> k3 = n.rc;AvlNode<AnyType> k2 = n.rc.lc;k1.rc = k2.lc;k3.lc = k2.rc;k2.lc = k1;k2.rc = k3;k1.height = Math.max(getHeight(k1.lc), getHeight(k1.rc)) + 1;k3.height = Math.max(getHeight(k3.lc), getHeight(k3.rc)) + 1;k2.height = Math.max(getHeight(k2.lc), getHeight(k2.rc)) + 1;// another method//k1.rc = rotateWithLeftChildren(k3);//return rotateWithRightChildren(k1);return k2;}
以上是平衡二叉树的插入和删除部分代码,经过初步测试暂时没有问题,如果有问题,也希望大家多多指出,多多交流。

1 0
原创粉丝点击