手写AVL树

public class AVLBinaryTree<E extends Comparable<E>> {

    Node<E> root;
    int size = 0;
    private static final int LH = 1;
    private static final int RH = -1;
    private static final int EH = 0;

    /*
     *         x                             y
     *        /  \                          /  \
     *      a     y       <----->         x     c
     *           /  \                    /  \
     *          b     c                 a    b
     */
    public void left_rotate(Node<E> x) {
        if (x != null) {
            Node<E> y = x.right;
            //1,b作为x的右孩子
            x.right = y.left;
            if (y.left != null) {
                y.left.parent = x;
            }
            //2,把y移到x的位置
            y.parent = x.parent;
            if (x.parent == null) {
                root = y;
            } else {
                if (x.parent.left == x) {
                    x.parent.left = y;
                } else if (x.parent.right == x) {
                    x.parent.right = y;
                }
            }
            //3,x作为y的左孩子
            y.left = x;
            x.parent = y;
        }
    }

    public void right_rotate(Node<E> y) {
        if (y != null) {
            Node<E> x = y.left;
            //1,b作为y的左孩子
            y.left = x.right;
            if (y.left != null) {
                y.left.parent = x;
            }
            //2,把x移到y的位置
            x.parent = y.parent;
            if (y.parent == null) {
                root = x;
            } else {
                if (y.parent.left == y) {
                    y.parent.left = x;
                } else if (y.parent.right == y) {
                    y.parent.right = x;
                }
            }
            //3,y作为x的右孩子
            x.right = y;
            y.parent = x;
        }
    }

   /**
	 * 右平衡操作,即结点t的不平衡是因为右子树过深
	 * 
	 * 1、如果新的结点插入到t的右孩子的右子树中,则直接进行左旋操作即可
	 *       
	 * 		 	t											 tr
	 * 		  /   \										   /     \
	 * 		 l	   tr			   左旋操作 				  t       rr
	 * 			 /   \			----------->             	 / \     /    \
	 * 			rl    rr								     l   rl rrl    rrr
	 * 				/   \
	 * 			 rrl 	rrr
	 
	 * 2、如果新的结点插入到t的右孩子的左子树中,则需要进行分情况讨论 
	 * 	情况a:当t的右孩子的左子树根节点的balance = LEFT_HIGH
	 * 
	 *			t						t							trl
	 *		   /  \					   /  \						   /   \
	 *		  2   tr		  tr右旋	  	  2	 trl		t左旋			   t    tr
	 *			  /  \	   ------->		  /  \		------->	      /  \     \
	 * 		  trl	  5					 6   tr					2	6  	   5	
	 * 			/							   \
	 * 		   6								    5 
	 * 情况b:当t的右孩子的左子树根节点的balance = RIGHT_HIGH
	 * 
	 *			t						t							trl
	 *		   /  \					   /  \						   /   \
	 *		  2   tr		  tr右旋	  	  2	 trl			t左旋		  t    tr
	 *			  /  \	   ------->		     \		------->	     /     /  \
	 * 			 trl	  5					     tr				   2	     6	  5	
	 * 			  \							 /  \
	 * 		   	   6						    6    5
	 
	 * 情况C:当t的右孩子的左子树根节点的balance = EQUAL_HIGH
	 *			t						t						    trl
	 *		   /  \					   /  \						   /   \
	 *		  2   tr		  右旋	  	  2	 trl 		左旋		  	  t    tr
	 *			  /  \	   ------->		  /  \		------->	      / \    / \
	 * 		   trl	  5					 6   tr					2	6  7   5	
	 * 			/ \							 /  \
	 * 		   6   7						     7    5
	 * */


    public void rightBalance(Node<E> t) {
        Node<E> tr = t.right;
        switch (tr.balance) {
            case RH://新的结点插入到t的右孩子的右子树中
                left_rotate(t);
                t.balance = EH;
                tr.balance = EH;
                break;
            case LH://新的结点插入到t的右孩子的左子树中
                Node<E> trl = tr.left;
                switch (trl.balance) {
                    case RH:
                        t.balance = LH;
                        tr.balance = EH;
                        trl.balance = EH;
                        break;
                    case LH:
                        t.balance = EH;
                        tr.balance = RH;
                        trl.balance = EH;
                        break;
                    case EH:
                        tr.balance = EH;
                        trl.balance = EH;
                        t.balance = EH;
                        break;

                }
                right_rotate(t.right);
                left_rotate(t);
                break;

        }
    }

  /**
	 * 左平衡操作,即结点t的不平衡是因为左子树过深
	 * 
	 * 1、如果新的结点插入到t的左孩子的左子树中,则直接进行右旋操作即可
	 * 				t									   tl
	 * 			   /  \			右旋操作				   /         \
	 * 			  tl   tr		------------->		  tll         t
	 * 			 /  \								 /	\        /   \
	 * 			tll  tlr						        lcll  lclr    tlr   tr 
	 * 			/  \
	 *         lcll   lclr
	 *         
	 * 2、如果新的结点插入到t的左孩子的右子树中,则需要进行分情况讨论
	 * 
	 * 	情况a:当t的左孩子的右子树根节点的balance = RIGHT_HIGH
	 * 			t						t						 	tlr
	 * 		   /  \					   /  \						   /  \
	 *         tl    6       左旋   tlr    6       右旋		      tl    t
	 *       /  \  		------->     /  \        -------->       /    /  \
	 *      3  tlr                 tl    5                     	3    5    6
	 *            \                /
	 *             5			  3
	 * 	情况b:当t的左孩子的右子树根节点的balance = LEFT_HIGH
	 * 
	 * 			t					    	t						   tlr
	 * 		   /  \					      /  \						   /  \
	 *       tl    6      		左旋   	tlr    6          右旋		  tl    t
	 *        /  \  		------->    /          -------->         / \    \
	 *       3  tlr                	  tl                            3   5    6
	 *          /                 	  / \
	 *         5   			    	 3   5
	 * 
	 * 	情况c:当t的左孩子的右子树根节点的balance = EQUAL_HIGH
	 * 
	 * 			t						t						   tlr
	 * 		   /  \					   /  \						   /  \
	 *        tl    7      左旋 	tlr    7          右旋		  tl   t
	 *        /  \  	------->    / \         -------->        / \   / \
	 *       3  tlr               tl   6                        3   5  6  7
	 *           / \              / \
	 *          5   6	        3	  5
	 * */


    public void leftBalance(Node<E> t) {
        Node<E> tl = t.left;
        switch (tl.balance) {
            case LH:
                right_rotate(t);
                tl.balance = EH;
                t.balance = EH;
                break;
            case RH:
                Node<E> tlr = tl.right;
                switch (tlr.balance) {
                    case LH:
                        t.balance = RH;
                        tl.balance = EH;
                        tlr.balance = EH;
                        break;
                    case RH:
                        t.balance = EH;
                        tl.balance = LH;
                        tlr.balance = EH;
                        break;
                    case EH:
                        t.balance = EH;
                        tl.balance = EH;
                        tlr.balance = EH;
                        break;

                    default:
                        break;
                }
                left_rotate(t.left);
                right_rotate(t);
                break;
        }
    }

    public boolean insertElement(E element) {
        Node<E> t = root;
        if (t == null) {
            root = new Node<E>(element, null);
            size = 1;
            root.balance = 0;
            return true;
        } else {
            //开始找到要插入的位置
            int cmp = 0;
            Node<E> parent;
            Comparable<? super E> e = (Comparable<? super E>) element;
            do {
                parent = t;
                cmp = e.compareTo(t.element);
                if (cmp < 0) {
                    t = t.left;
                } else if (cmp > 0) {
                    t = t.right;
                } else {
                    return false;
                }
            } while (t != null);
            //开始插入数据
            Node<E> child = new Node<E>(element, parent);
            if (cmp < 0) {
                parent.left = child;
            } else {
                parent.right = child;
            }
            //节点已经放到了树上
            //检查平衡,回溯查找
            while (parent != null) {
                cmp = e.compareTo(parent.element);
                if (cmp < 0) {
                    parent.balance++;
                } else {
                    parent.balance--;
                }
                if (parent.balance == 0) {//如果插入后还是平衡树,不用调整
                    break;
                }
                if (parent.balance == 2 || parent.balance == -2) {
                    //出现了平衡的问题,需要修正
                    fixAfterInsertion(parent);
                    break;
                } else {
                    parent = parent.parent;
                }
            }
        }
        size++;
        return true;
    }

    private void fixAfterInsertion(Node<E> parent) {
        if (parent.balance == 2) {
            leftBalance(parent);
        }
        if (parent.balance == -2) {
            rightBalance(parent);
        }
    }

    public class Node<E extends Comparable<E>> {
        E element;
        int balance = 0;//平衡因子
        Node<E> left;
        Node<E> right;
        Node<E> parent;

        public Node(E element, Node<E> parent) {
            this.element = element;
            this.parent = parent;
        }
    }
}

 

    原文作者:AVL树
    原文地址: https://blog.csdn.net/hxl517116279/article/details/85141667
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞