Java基础 - 平衡二叉查找树(AVL树)

来源:互联网 发布:svg获取坐标 path.js 编辑:程序博客网 时间:2024/04/28 10:41

花了三天时间,画了一本子的树。终于应该是做出来了。

首先一点树的四种轮转,单左旋,单右旋,双向左旋,双向右旋都是没问题的。还有就是平衡树的添加功能是可以的。删除功能楼主不敢说。


package com.yc.tree;import java.util.ArrayDeque;import java.util.ArrayList;import java.util.Deque;import java.util.List;/** * @author wb * @param <T> *  *  * 平衡二叉查找树(height balanced binary search tree)在1962年由Adelson-Velskii和 * Landis提出,因此又称为AVL树。AVL树定义为:一棵空树是平衡二叉查找树;假设T不是空的树,TL和TR分别是此 * 二叉树的左子树和右子树,如符合下列两个条件,则称T为平衡二叉查找树:(1)TL和TR亦是平衡二叉查找树;(2) * |hL - hR| <= 1,其中hL和hR分别是TL和TR的高度。 *  * 在一棵二叉树中有一个节点p,其左子树(TL)和右子树(TR)的高度分别为hL和hR,而BF(p)表示p节点的平衡因子 * (balance factory)。平衡因子的计算为hL - hR。在一棵AVL树中,每一个节点的平衡因子为-1或0或1, * 即|hL - hR| < 2。 *  * 如下图不是一个平衡二叉查找树(AVL树)。因为为30节点的平衡因子的绝对值为2. *               50 BF=1 *   ││ *   BF=-2 30────────┘└─────────70 BF=1 * │  │ * └──40 BF=1 BF=0 60──┘ * │ *   BF=0 35───┘ * 图xx.xx 一棵二叉树的平衡因子 *  * * 插入: * 向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,接着自底向上向根节点折回, * 于在插入期间成为不平衡的所有节点上进行旋转来完成。因为折回到根节点的路途上最多有 1.5 乘 log n  * 个节点,而每次 AVL 旋转都耗费恒定的时间,插入处理在整体上耗费 O(log n) 时间。 在平衡的的 * 二叉排序树Balanced BST上插入一个新的数据元素e的递归算法可描述如下: 若BBST为空树,则插入 * 一个数据元素为e的新结点作为BBST的根结点,树的深度增1;  若e的关键字和BBST的根结点的关键字相等, * 则不进行;  若e的关键字小于BBST的根结点的关键字,而且在BBST的左子树中不存在和e有相同关键字的结点, * 则将e插入在BBST的左子树上,并且当插入之后的左子树深度增加(+1)时,分别就下列不同情况处理之:  * BBST的根结点的平衡因子为-1(右子树的深度大于左子树的深度,则将根结点的平衡因子更改为0,BBST的深度不变; * BBST的根结点的平衡因子为0(左、右子树的深度相等):则将根结点的平衡因子更改为1,BBST的深度增1;   *  BBST的根结点的平衡因子为1(左子树的深度大于右子树的深度):则若BBST的左子树根结点的平衡因子为1: *  则需进行单向右旋平衡处理,并且在右旋处理之后,将根结点和其右子树根结点的平衡因子更改为0,树的深度不变;  *  若e的关键字大于BBST的根结点的关键字,而且在BBST的右子树中不存在和e有相同关键字的结点,则将e插入在BBST *  的右子树上,并且当插入之后的右子树深度增加(+1)时,分别就不同情况处理之。 *   *  删除: *  从AVL树中删除可以通过把要删除的节点向下旋转成一个叶子节点,接着直接剪除这个叶子节点来完成。 因为在旋转成 *  叶子节点期间最多有 log n个节点被旋转,而每次 AVL 旋转耗费恒定的时间,删除处理在整体上耗费 O(log n) 时间。 *   *  (我采用的是:调整原则如下(其中privot是指要删除节点的父节点) *  先采用二叉排序树的删除方法(将要删除节点的左子树的最大值替换他)。再进行如下判断操作 *  当pivot.BF >= 0时 *  (privot.left.BF >= 0    用LL型) *  (privot.left.BF < 0    用LR型) *   *  当pivot.BF < 0时 *  (privot.right.BF >= 0    用RL型) *  (privot.right.BF < 0    用RR型) *  )这种方法的缺点我想应该是无论什么情况他都会轮转。但在有的情况下它是没有必要去轮转的,这就很耗时好资源吧。 *   *   *  查找: *  在AVL树中查找同在一般BST完全一样的进行,所以耗费 O(log n) 时间,因为AVL树总是保持平衡的。 *  不需要特殊的准备,树的结构不会由于查询而改变。(这是与伸展树查找相对立的,它会因为查找而变更树结构。) */public class HeightBalanBinSearchTree <T extends Comparable<T>>{private static final int LEFT_HEAVY = -1;private static final int BALANCED = 0;private static final int RIGHT_HEAVY = 1;private static final int RIGHT_RIGHT_HEAVY = 2;private static final int LEFT_LEFT_HEAVY = -2;public class AVLNode {//用于跟踪左子树与右子树是否等高int balanceFactory;T data;AVLNode left;AVLNode right;//想来想去这个还是加上吧AVLNode parent;public AVLNode(int balanceFactory, T data, AVLNode left, AVLNode right, AVLNode parent){this.balanceFactory = balanceFactory;this.data = data;this.left = left;this.right = right;this.parent = parent;}public String toString(){return "[BF=" + balanceFactory + ",data=" + data + "]";}}//avl树的根节点private AVLNode root;public HeightBalanBinSearchTree(){}public HeightBalanBinSearchTree(T data){root = new AVLNode(BALANCED, data, null, null, null);}/** * 往AVL树中添加数据元素为data的节点 * @param data */public void add(T data){if(root == null){root = new AVLNode(BALANCED, data, null, null, null);}else{AVLNode current = root;AVLNode parent = null;int imp = 0;do{parent = current;imp = data.compareTo(current.data);if(imp > 0){current = current.right;}else{current = current.left;}}while(current != null);AVLNode newNode = new AVLNode(BALANCED, data, null, null, parent);if(imp > 0){parent.right = newNode;}else{parent.left = newNode;}//添加新节点后改变其祖先节点的平衡因子并重新平衡树reBalacedForAdd(newNode);}}/** * 删除指定元素的节点 * @param data */public void remove(T data){AVLNode delNode = getAVLNode(data);reBalacedForRemove(delNode);}//按照排序二叉树的方式删除指定元素的节点private void reBalacedForRemove(AVLNode target){if(target == null){//如果未找到return;}if(target.left == null && target.right == null){//如果要删除节点的左、右子树为空(叶子节点)if(target == root){root = null;}else{reBalacedForRemoveHelp(target);if(target == target.parent.left){target.parent.left = null;}else{target.parent.right = null;}//向上引用也赋空target.parent = null;  }}else if(target.left != null && target.right == null){ //如果要删除的节点只有左子树(还有一点要记住,就是它已经是平衡的)//如果要删除的节点是根节点if(root == target){root = target.left;target.left.parent = null; //不能让它指回去}else{//如果要删除节点是其父节点的左子节点if(target == target.parent.left){target.parent.left = target.left;}else{target.parent.right = target.left;}target.left.parent = target.parent; //指回去(到这只是要删除的节点从树中删除了,但并未在堆内存中删除,它的引用还是存在的)reBalacedForRemoveHelp(target.left);target.parent = target.left = target.right = null;}}else if(target.right != null && target.left == null){ //如果要删除的节点只有右子树if(root == target){root = target.right;target.right.parent = null; //不能让它指回去}else{if(target == target.parent.left){target.parent.left = target.right;}else{target.parent.right = target.right;}target.right.parent = target.parent;reBalacedForRemoveHelp(target.right);target.parent = target.left = target.right = null;}}else if(target.left != null && target.right != null){ //如果要删除元素的节点既有右子树,也有左子树if(root == target){AVLNode leftMaxNode = target.left;while(leftMaxNode.right != null){leftMaxNode = leftMaxNode.right;}root = leftMaxNode;if(target.left.data.equals(leftMaxNode.data)){leftMaxNode.right = target.right;target.right.parent = leftMaxNode;//jialeftMaxNode.parent = null;target.right = target.parent = target.left = null;leftMaxNode.balanceFactory = target.balanceFactory - 1;reBalacedForRemoveHelpAndHelp(leftMaxNode);}else{AVLNode tmpNode = new AVLNode(0,null,leftMaxNode.left,null,leftMaxNode.parent);leftMaxNode.parent.right = tmpNode;leftMaxNode.left = target.left;leftMaxNode.right = target.right;//leftMaxNode.balanceFactory = target.balanceFactory;target.left.parent = leftMaxNode;target.right.parent = leftMaxNode;target.right = target.parent = target.left = null;leftMaxNode.parent = null;reBalacedForRemoveHelp(tmpNode);tmpNode.parent.right = tmpNode.left;if(tmpNode.left != null){tmpNode.left.parent = leftMaxNode.parent;}tmpNode = null;}}else{AVLNode leftMaxNode = target.left;while(leftMaxNode.right != null){leftMaxNode = leftMaxNode.right;}if(target.left.data.equals(leftMaxNode.data)){leftMaxNode.right = target.right;leftMaxNode.parent = target.parent;if(target == target.parent.left){target.parent.left = leftMaxNode;}else{target.parent.right = leftMaxNode;}target.right = target.parent = target.left = null;leftMaxNode.balanceFactory = target.balanceFactory - 1;reBalacedForRemoveHelpAndHelp(leftMaxNode);}else{AVLNode tmpNode = new AVLNode(0,null,leftMaxNode.left,null,leftMaxNode.parent);leftMaxNode.parent.right = tmpNode;if(target == target.parent.left){target.parent.left = leftMaxNode;}else{target.parent.right = leftMaxNode;}leftMaxNode.parent = target.parent;leftMaxNode.left = target.left;leftMaxNode.right = target.right;target.left.parent = leftMaxNode;target.right.parent = leftMaxNode;target.right = target.parent = target.left = null;reBalacedForRemoveHelp(tmpNode);tmpNode.parent.right = tmpNode.left;if(tmpNode.left != null){tmpNode.left.parent = leftMaxNode.parent;}tmpNode = null;}}}}//删除节点后的平衡(动词)树private void reBalacedForRemoveHelp(AVLNode node){if(node.parent != null){if(node.parent.left != null && node.parent.right != null && node.left == null && node.right == null){if(node == node.parent.left){node.parent.balanceFactory -= 1;reBalacedForRemoveHelpAndHelp(node.parent);}else if(node == node.parent.right){node.parent.balanceFactory += 1;reBalacedForRemoveHelpAndHelp(node.parent);}}else{if(node == node.parent.left){node.parent.balanceFactory -= 1;}else if(node == node.parent.right){node.parent.balanceFactory += 1;}AVLNode current = node.parent;while(current.parent != null){if(current.balanceFactory == BALANCED){if(current == current.parent.left){current.parent.balanceFactory -= 1;if(current.parent.balanceFactory == LEFT_LEFT_HEAVY){//等于-2,失去平衡if(typeOfRemove(current.parent, LEFT_LEFT_HEAVY).equals("RR")){type_rR(current.parent);break;}else if(typeOfRemove(current.parent, LEFT_LEFT_HEAVY).equals("RL")){type_rL(current.parent, true);break;}else{//what are U nongshalie.}}}else if(current == current.parent.right){current.parent.balanceFactory += 1;if(current.parent.balanceFactory == RIGHT_RIGHT_HEAVY){//等于2,失去平衡if(typeOfRemove(current.parent, RIGHT_RIGHT_HEAVY).equals("LL")){type_lL(current.parent);break;}else if(typeOfRemove(current.parent, RIGHT_RIGHT_HEAVY).equals("LR")){type_lR(current.parent, true);break;}else{//what are U nongshalie.}}}}else{break;}current = current.parent;}}}}private void reBalacedForRemoveHelpAndHelp(AVLNode current){if(current.balanceFactory == RIGHT_RIGHT_HEAVY){//等于2,失去平衡if(typeOfRemove(current, RIGHT_RIGHT_HEAVY).equals("LL")){type_lL(current);reBalacedForRemoveHelp(current.parent);}else if(typeOfRemove(current, RIGHT_RIGHT_HEAVY).equals("LR")){type_lR(current, true);reBalacedForRemoveHelp(current.parent);}else{//what are U nongshalie.}}else if(current.balanceFactory == LEFT_LEFT_HEAVY){if(typeOfRemove(current, LEFT_LEFT_HEAVY).equals("RR")){type_rR(current);reBalacedForRemoveHelp(current.parent);}else if(typeOfRemove(current, LEFT_LEFT_HEAVY).equals("RL")){type_rL(current, true);reBalacedForRemoveHelp(current.parent);}else{//what are U nongshalie.}}}//改变其祖先节点的平衡因子并重新平衡树private void reBalacedForAdd(AVLNode node){if(node.parent.left != null && node.parent.right != null){if(node == node.parent.left){node.parent.balanceFactory += 1;return;}else if(node == node.parent.right){node.parent.balanceFactory -= 1;return;}}else{if(node == node.parent.left){node.parent.balanceFactory += 1;}else if(node == node.parent.right){node.parent.balanceFactory -= 1;}AVLNode current = node.parent;while(current.parent != null){if(current.balanceFactory != BALANCED){if(current == current.parent.left){current.parent.balanceFactory += 1;if(current.parent.balanceFactory == RIGHT_RIGHT_HEAVY){//等于2,失去平衡if(typeOfAdd(node, current.parent).equals("LL")){type_lL(current.parent);break;}else if(typeOfAdd(node, current.parent).equals("LR")){type_lR(current.parent, false);break;}}}else if(current == current.parent.right){current.parent.balanceFactory -= 1;if(current.parent.balanceFactory == LEFT_LEFT_HEAVY){//等于-2,失去平衡if(typeOfAdd(node, current.parent).equals("RL")){type_rL(current.parent, false);break;}else if(typeOfAdd(node, current.parent).equals("RR")){type_rR(current.parent);break;}}}current = current.parent;}else{break;}}}}//返回调整的类型是LL还是RR还是LR还是RLprivate String typeOfAdd(AVLNode node, AVLNode bFIs2Node){AVLNode current = node;while(true){//不知道有没有风险if(bFIs2Node.left != null){if(current == bFIs2Node.left.left){return "LL";}if(current == bFIs2Node.left.right){return "LR";}}else if(bFIs2Node.right != null){if(current == bFIs2Node.right.right){return "RR";}if(current == bFIs2Node.right.left){return "RL";}}current = current.parent;}}private String typeOfRemove(AVLNode bFIs2Node, int bf){if(bFIs2Node != null){if(bf == RIGHT_RIGHT_HEAVY){ //左边高if(bFIs2Node.left != null){if(bFIs2Node.left.balanceFactory >= BALANCED){return bFIs2Node.left.left != null ? "LL" : "";}else{return bFIs2Node.left.right != null ? "LR" : "";}}}else if(bf == LEFT_LEFT_HEAVY){ //右边高if(bFIs2Node.right != null){if(bFIs2Node.right.balanceFactory >= BALANCED){return bFIs2Node.right.left != null ? "RL" : "";}else{return bFIs2Node.right.right != null ? "RR" : "";}}}}return "";}/*** * LL型(单右旋) * pl * │   ││ * l───┘->  ll───┘└───p * │ * ll───┘ *  */private void type_lL(AVLNode p){if(p != null){AVLNode l = p.left;//AVLNode ll = l.left;if(p.parent == null){ //p是根root = l;l.parent = null;p.left = l.right;l.right = p;p.parent = l;if(l.balanceFactory == RIGHT_HEAVY){ //1//l.balanceFactory = BALANCED;//p.balanceFactory = BALANCED;l.balanceFactory -= RIGHT_HEAVY;p.balanceFactory -= RIGHT_RIGHT_HEAVY;}else if(l.balanceFactory == BALANCED){//0 //l.balanceFactory = LEFT_HEAVY;//p.balanceFactory = BALANCED;l.balanceFactory -= RIGHT_HEAVY;p.balanceFactory -= RIGHT_HEAVY;}else{/*l.balanceFactory -= RIGHT_HEAVY;p.balanceFactory -= RIGHT_HEAVY;*/}}else{if(p == p.parent.left){p.parent.left = l;}else if(p == p.parent.right){p.parent.right = l;}l.parent = p.parent;p.left = l.right;l.right = p;p.parent = l;if(l.balanceFactory == RIGHT_HEAVY){ //1//l.balanceFactory = BALANCED;//p.balanceFactory = BALANCED;l.balanceFactory -= RIGHT_HEAVY;p.balanceFactory -= RIGHT_RIGHT_HEAVY;}else if(l.balanceFactory == BALANCED){//0 //l.balanceFactory = LEFT_HEAVY;//p.balanceFactory = BALANCED;l.balanceFactory -= RIGHT_HEAVY;p.balanceFactory -= RIGHT_HEAVY;}else {/*l.balanceFactory -= RIGHT_HEAVY;p.balanceFactory -= RIGHT_HEAVY;*/}}}}/** * RR型(单向左旋) * pr * │-> ││ * └───r    p───┘└───rr * │ * └──rr */private void type_rR(AVLNode p){AVLNode r = p.right;//AVLNode rr = r.right;if(p.parent == null){ //p是根root = r;r.parent = null;p.right = r.left;r.left = p;p.parent = r;if(r.balanceFactory == LEFT_HEAVY){ //-1//r.balanceFactory = BALANCED;r.balanceFactory += RIGHT_HEAVY;p.balanceFactory += RIGHT_RIGHT_HEAVY;}else if(r.balanceFactory == BALANCED){//0//r.balanceFactory = RIGHT_HEAVY;//p.balanceFactory = BALANCED;r.balanceFactory += RIGHT_HEAVY;p.balanceFactory += RIGHT_HEAVY;}else {/*r.balanceFactory += RIGHT_HEAVY;p.balanceFactory += RIGHT_HEAVY;*/}}else{if(p == p.parent.left){p.parent.left = r;}else if(p == p.parent.right){p.parent.right = r;}r.parent = p.parent;p.right = r.left;r.left = p;p.parent = r;if(r.balanceFactory == LEFT_HEAVY){ //-1//r.balanceFactory = BALANCED;r.balanceFactory += RIGHT_HEAVY;p.balanceFactory += RIGHT_RIGHT_HEAVY;}else if(r.balanceFactory == BALANCED){//0//r.balanceFactory = RIGHT_HEAVY;//p.balanceFactory = BALANCED;r.balanceFactory += RIGHT_HEAVY;p.balanceFactory += RIGHT_HEAVY;}else {/*r.balanceFactory += RIGHT_HEAVY;p.balanceFactory += RIGHT_HEAVY;*/}}}/** * LR型(双向右旋(先左旋再右旋)) * p * │lr * l───┘-》 ││ * │ l──┘└───p * └───lr *  * @param p */private void type_lR(AVLNode p, boolean isRemove){/*AVLNode l = p.left;AVLNode lr = l.right;type_rR(l);type_lL(p);if(isRemove){lr.balanceFactory += RIGHT_HEAVY;}*/AVLNode l = p.left;AVLNode lr = l.right;if(p.parent == null){ //是根root = lr;l.right = lr.left;if(lr.left != null){lr.left.parent = l;}p.left = lr.right;if(lr.right != null){lr.right.parent = p;}lr.left = l;lr.right = p;l.parent = lr;p.parent = lr;lr.parent = null;if(lr.balanceFactory == RIGHT_HEAVY){ //1p.balanceFactory -= 3;l.balanceFactory += 1;lr.balanceFactory -= 1;}else if(lr.balanceFactory == BALANCED){//0p.balanceFactory -= 2;l.balanceFactory += 1;}else if(lr.balanceFactory == LEFT_HEAVY){//-1p.balanceFactory -= 2;l.balanceFactory += 2;lr.balanceFactory += 1;}}else{l.right = lr.left;if(lr.left != null){lr.left.parent = l;}p.left = lr.right;if(lr.right != null){lr.right.parent = p;}lr.left = l;lr.right = p;lr.parent = p.parent;if(p == p.parent.left){p.parent.left = lr;}if(p == p.parent.right){p.parent.left = lr;}l.parent = lr;p.parent = lr;if(lr.balanceFactory == RIGHT_HEAVY){ //1p.balanceFactory -= 3;l.balanceFactory += 1;lr.balanceFactory -= 1;}else if(lr.balanceFactory == BALANCED){ //0p.balanceFactory -= 2;l.balanceFactory += 1;}else if(lr.balanceFactory == LEFT_HEAVY){ //-1p.balanceFactory -= 2;l.balanceFactory += 2;lr.balanceFactory += 1;}}}/** * RL型(双向左旋旋(先右旋再左旋)) * p * │  rl * └──r-》 ││ *    │ p──┘└───r *       rl───┘ *  * @param p */private void type_rL(AVLNode p, boolean isRemove){/*AVLNode r = p.right;AVLNode rl = r.left;type_lL(r);type_rR(p);if(isRemove){rl.balanceFactory -= RIGHT_HEAVY;}*/AVLNode r = p.right;AVLNode rl = r.left;if(p.parent == null){ //如果是根root = rl;r.left = rl.right;if(rl.right != null){rl.right.parent = r;}p.right = rl.left;if(rl.left != null){rl.left.parent = p;}rl.left = p;rl.right = r;rl.parent = p.parent;p.parent = rl;r.parent = rl;if(rl.balanceFactory == RIGHT_HEAVY){ //1p.balanceFactory += 2;r.balanceFactory -= 2;rl.balanceFactory -= 1;}else if(rl.balanceFactory == BALANCED){p.balanceFactory += 2;r.balanceFactory -= 1;}else if(rl.balanceFactory == LEFT_HEAVY){p.balanceFactory += 3;r.balanceFactory -= 1;rl.balanceFactory += 1;}}else{r.left = rl.right;if(rl.right != null){rl.right.parent = r;}p.right = rl.left;if(rl.left != null){rl.left.parent = p;}rl.left = p;rl.right = r;rl.parent = p.parent;if(p == p.parent.left){p.parent.left = rl;}if(p == p.parent.right){p.parent.left = rl;}p.parent = rl;r.parent = rl;if(rl.balanceFactory == RIGHT_HEAVY){ //1p.balanceFactory += 2;r.balanceFactory -= 2;rl.balanceFactory -= 1;}else if(rl.balanceFactory == BALANCED){p.balanceFactory += 2;r.balanceFactory -= 1;}else if(rl.balanceFactory == LEFT_HEAVY){p.balanceFactory += 3;r.balanceFactory -= 1;rl.balanceFactory += 1;}}}//获取指定数据元素的节点private AVLNode getAVLNode(T data){if(root == null){return null;}AVLNode node = root;int compInt = 0;while(node != null){compInt = data.compareTo(node.data);if(compInt > 0){node = node.right;}else if(compInt < 0){node = node.left;}else{return node;}}return null;}//广度优先遍历public List<AVLNode> breadthFirstSearch(){return cBreadthFirstSearch(root);}private List<AVLNode> cBreadthFirstSearch(AVLNode node) {List<AVLNode> nodes = new ArrayList<AVLNode>();Deque<AVLNode> deque = new ArrayDeque<AVLNode>();if(node != null){deque.offer(node);}while(!deque.isEmpty()){AVLNode tmp = deque.poll();nodes.add(tmp);if(tmp.left != null){deque.offer(tmp.left);}if(tmp.right != null){deque.offer(tmp.right);}}return nodes;}public static void main(String[] args) {HeightBalanBinSearchTree<Integer> tree = new HeightBalanBinSearchTree<Integer>();tree.add(20);tree.add(23);tree.add(17);tree.add(19);tree.add(21);tree.add(26);tree.add(14);tree.add(18);tree.add(11);tree.add(16);tree.add(22);tree.add(24);tree.add(27);//tree.add(15);System.out.println( tree.breadthFirstSearch());tree.remove(17);System.out.println( tree.breadthFirstSearch());}}


测试结果:

[[BF=1,data=20], [BF=1,data=17], [BF=0,data=23], [BF=-1,data=14], [BF=1,data=19], [BF=-1,data=21], [BF=0,data=26], [BF=0,data=11], [BF=1,data=16], [BF=0,data=18], [BF=0,data=22], [BF=0,data=24], [BF=0,data=27], [BF=0,data=15]][[BF=0,data=20], [BF=0,data=16], [BF=0,data=23], [BF=0,data=14], [BF=1,data=19], [BF=-1,data=21], [BF=0,data=26], [BF=0,data=11], [BF=0,data=15], [BF=0,data=18], [BF=0,data=22], [BF=0,data=24], [BF=0,data=27]]



0 0