AVL树实现

       看了很长时间关于树的知识、今天自己尝试写一个二叉平衡树,个别代码稍微参考了一下,大部分是自己编写完成的。自己动手写的最大感受就是算法想起来比较简单,然实现起来还挺复杂的吧,还有,AVL树的插入和删除真不是一个级别的,本来想着应该类似的差不多,结果发现差好多啊,插入差不多半小时就写完了,删除用了一天尴尬、蓝瘦香菇......

package com.gaoxue.LeetCode;

public class AVLTreeGX<T extends Comparable<T>>{

	private Node<T> root;
	
	private static class Node<T>{
		int height;
		T data;
		Node<T> left;
		Node<T> right;
		public Node(Node<T> left,Node<T> right,T data) {
			this.data = data;
			this.left = left;
			this.right = right;
			this.height = 0;
		}
	}
	public Node<T> insert(T data){
		return root = insert(data,root);
	}
	public Node<T> insert(T data,Node<T> node){
		if(node == null)
			return new Node<T>(null,null,data);
		int CompareResult = data.compareTo(node.data);
		if(CompareResult>0) {
			node.right = insert(data,node.right);
			if(getHeight(node.right)-getHeight(node.left)==2) {
				//左右子树高度差为2则不符合AVL树的性质,需要进行旋转恢复平衡
				int CompareResult2 = data.compareTo(node.right.data);
				//判断在子树的左右哪边插入新的结点以确定使用单次或者二次旋转
				if(CompareResult2>0) {
					node = LeftRotate(node);
				}else {
					node = RightLeftRotate(node);
				}
			}
		}else if(CompareResult<0) {
			node.left = insert(data,node.left);
			if(getHeight(node.left)-getHeight(node.right)==2) {
				int CompareResult3 = data.compareTo(node.left.data);
				if(CompareResult3<0) {
					node = RightRotate(node);
				}else {
					node = LeftRightRotate(node);
				}
			}
		}
		node.height = Math.max(getHeight(node.left), getHeight(node.right))+1;
		return node;
	}
	public Node<T> LeftRotate(Node<T> node) {
		Node<T> rightNode = node.right;
        node.right = rightNode.left;
        rightNode.left = node;
        // 旋转结束计算树高
        node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
        rightNode.height = Math.max(node.height, getHeight(rightNode.right)) + 1;
        return rightNode;
	}
	public Node<T> RightRotate(Node<T> node) {
		Node<T> leftNode = node.left;
        node.left = leftNode.right;
        leftNode.right = node;
        // 旋转结束计算树高
        node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
        leftNode.height = Math.max(getHeight(leftNode.left), node.height) + 1;
        return leftNode;
	}
	public Node<T> LeftRightRotate(Node<T> node) {
		node.left = LeftRotate(node.left);
		node = RightRotate(node);
		return node;
	}
	public Node<T> RightLeftRotate(Node<T> node) {
		node.right = RightRotate(node.right);
		node = LeftRotate(node);
		return node;
	}
	public void MiddleTraversal(Node<T> root) {
		if(root.left!=null)
			MiddleTraversal(root.left);
		System.out.print(root.data+" ");
		if(root.right!=null)
			MiddleTraversal(root.right);
	}
	public int getHeight(Node<T> node) {
		return node==null?-1:node.height;
	}
	public Node<T> remove(T data){
		return root = remove(root,data);
	}
	private Node<T> remove(Node<T> node,T data) {
        if (node == null) {
            return null;
        }
        int compareResult = data.compareTo(node.data);
        if (compareResult == 0) {
            if (node.left != null && node.right != null) {
            	// 此节点存在左右子树
                int balance = getHeight(node.left) - getHeight(node.right);
                Node<T> temp = node;
                // 保存需要进行删除的node节点
                if (balance == -1) {
                    // 与右子树的最小值进行交换
                    exChangeRightData(node, node.right);
                } else {
                    // 与左子树的最大值进行交换
                    exChangeLeftData(node, node.left);
                }
                // 此时已经交换完成并且把节点删除完成,则需要重新计算该节点的树高
                temp.height = Math.max(getHeight(temp.left), getHeight(temp.right)) + 1;
                // 注意此处,返回的是temp,也就是保存的需要删除的节点,而不是替换的节点
                return temp;
            } else {
                // 此处隐含了一个node.left ==null && node.right == null 的条件,这时返回null
                return node.left != null ? node.left : node.right;
            }
        } else if (compareResult > 0) {
            node.right = remove(node.right,data);
            node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
            if (getHeight(node.left) - getHeight(node.right) == 2) {// 进行旋转
                Node<T> leftSon = node.left;
                if (getHeight(leftSon.left) > getHeight(leftSon.right)) {
                    node = RightRotate(node);
                } else {
                    node = LeftRightRotate(node);
                }
            }
            return node;
        } else if (compareResult < 0) {
            node.left = remove(node.left,data);
            node.height = Math.max(getHeight(node.left), getHeight(node.right)) + 1;
            if (getHeight(node.right) - getHeight(node.left) == 2) {
                Node<T> rightSon = node.right;
                if (rightSon.right.height > rightSon.left.height) {
                    node = LeftRotate(node);
                } else {
                    node = RightLeftRotate(node);
                }
            }
            return node;
        }
        return null;
    }

    private Node<T> exChangeLeftData(Node<T> node, Node<T> right) {
        if (right.right != null) {
            right.right = exChangeLeftData(node, right.right);
        } else {
            node.data = right.data;
            // 此处已经把替换节点删除
            return right.left;
        }
        right.height = Math.max(getHeight(right.left), getHeight(right.right)) + 1;
        int isbanlance = getHeight(right.left) - getHeight(right.right);
        if (isbanlance == 2) {
            Node<T> leftSon = node.left;
            if (getHeight(leftSon.left) > getHeight(leftSon.right)) {
                return node = RightRotate(node);
            } else {
                return node = LeftRightRotate(node);
            }
        }
        return right;
    }

    private Node<T> exChangeRightData(Node<T> node, Node<T> left) {
        if (left.left != null) {
            left.left = exChangeRightData(node, left.left);
        } else {
            node.data = left.data;
            // 此处已经把替换节点删除
            return left.right;
        }
        left.height = Math.max(getHeight(left.left), getHeight(left.right)) + 1;
        // 回溯判断left是否平衡,如果不平衡则进行左旋操作。
        int isbanlance = getHeight(left.left) - getHeight(left.right);
        if (isbanlance == -2) {// 进行旋转
            Node<T> rightSon = node.right;
            // 判断是否需要进行两次右旋还是一次右旋
            // 判断条件就是比较rightSon节点的左右子节点树高
            if (getHeight(rightSon.left) > getHeight(rightSon.right)) {
                return node = LeftRotate(node);
            } else {
                // 先右旋再左旋
                return node = RightRotate(node);
            }
        }
        return left;
    }
	public static void main(String args[]) {
        AVLTreeGX<Integer> tree = new AVLTreeGX<Integer>();
        int array[] = {4,5,10,7,8,9,15,30};
        for (int i = 0; i < array.length; i++) {
            tree.insert(array[i]);
        }
        tree.MiddleTraversal(tree.root);
        System.out.println();
        tree.remove(4);
        tree.MiddleTraversal(tree.root);
    }	
}
       可能有些地方还存在一些问题,但真的不能再测试了、脑子要炸了,就一直一直画树、测试数据都写了四五页了,有谁发现了问题一定记得纠正哈~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值