Java数据结构--平衡二叉树

DEMO地址:
https://github.com/zhaopingfu/MDataStruct/blob/master/src/com/pf/%E6%A0%91/AVLBintrayTree.java

在这里有一些资源,辅助看的:
https://github.com/zhaopingfu/MDataStruct/tree/master/resources/%E6%A0%91/AVL%E6%A0%91

  • 平衡二叉树是一种二叉排序树,其中每一个节点的左子树和右子树的高度差至多等于1.

  • 平衡因子:二叉树上节点的左子树深度减去右子树的深度的值成为平衡因子BF(Balance Factor)。

  • 最小不平衡子树:距离插入节点最近的,且平衡因子的绝对值大于1的节点为根的子树为最小不平衡树。

这里写图片描述

  • 构建AVL树

    这里写图片描述

    /**
     * @author zhaopf
     * @version 1.0
     * @QQ: 1308108803
     * @date 2017年12月25日
     * 平衡二叉树
     */
    public class AVLBintrayTree<E extends Comparable<E>> {
        /**
         * 根节点
         */
        private Node<E> root;
        /**
         * 树的节点
         */
        private int size;
        /**
         * 左边高,左边减去右边
         */
        private static final int LEFT_HEIGHT = 1;
        /**
         * 两边一样高,左边减去右边
         */
        private static final int EQUALS_HEIGHT = 0;
        /**
         * 右边高,左边减去右边
         */
        private static final int RIGHT_HEIGHT = -1;
    
        /**
         * 添加一个元素
         *
         * @param element
         * @return
         */
        public boolean put(E element) {
            if (element == null) {
                return false;
            }
            Node<E> t = root;
            if (t == null) {
                root = new Node<>(element, null);
                size++;
                return true;
            }
            // 开始添加元素
            Node<E> parent = null;
            Comparable<? super E> e = element;
            int compare;
            // 查找父节点
            do {
                parent = t;
                compare = e.compareTo(t.element);
                if (compare > 0) {
                    t = t.right;
                } else if (compare < 0) {
                    t = t.left;
                } else {
                    return false;
                }
            } while (t != null);
            // 添加到父节点上
            Node<E> newNode = new Node<>(element, parent);
            compare = newNode.element.compareTo(parent.element);
            if (compare > 0) {
                parent.right = newNode;
            } else if (compare < 0) {
                parent.left = newNode;
            }
            // 检查平衡问题
            while (parent != null) {
                compare = newNode.element.compareTo(parent.element);
                // 如果节点是添加到右子树
                if (compare > 0) {
                    parent.balance--;
                } else {
                    parent.balance++;
                }
                // 还是平衡的
                if (parent.balance == 0) {
                    break;
                }
                // 如果出现了平衡问题
                if (Math.abs(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);
            } else if (parent.balance == -2) {
                rightBalance(parent);
            }
        }
    
        /**
         * 中序遍历节点
         *
         * @return
         */
        public List<Node<E>> midSelectTree() {
            List<Node<E>> result = new ArrayList<>(size);
            Node<E> temp = root;
            if (temp == null) {
                return result;
            }
            Stack<Node<E>> stack = new Stack<>();
            // 添加根节点
            stack.add(temp);
            Set<Node<E>> set = new HashSet<>(size);
            while (!stack.isEmpty()) {
                Node<E> t = stack.pop();
                if (t.getLeft() != null && !set.contains(t.getLeft())) {
                    if (t.getRight() != null) {
                        stack.push(t.getRight());
                    }
                    stack.push(t);
                    stack.push(t.getLeft());
                } else {
                    set.add(t);
                    result.add(t);
                    if (t.getRight() != null && !stack.contains(t.getRight())) {
                        stack.push(t.getRight());
                    }
                }
            }
            return result;
        }
    
        /**
         * 左平衡操作,节点t的不平衡是因为左子树过深
         *
         * @param t
         */
        private void leftBalance(Node<E> t) {
            if (t == null || t.left == null) {
                return;
            }
            Node<E> tLeftChild = t.left;
            switch (tLeftChild.balance) {
                // 如果新的结点插入到t的左孩子的左子树中,则直接进行右旋操作即可
                case LEFT_HEIGHT:
                    t.balance = EQUALS_HEIGHT;
                    tLeftChild.balance = EQUALS_HEIGHT;
                    // 右旋
                    rightRotate(t);
                    break;
                case EQUALS_HEIGHT:
                    break;
                // 如果新的结点插入到t的左孩子的右子树中,则需要进行分情况讨论
                case RIGHT_HEIGHT:
                    Node<E> tLeftChildRightChild = tLeftChild.right;
                    switch (tLeftChildRightChild.balance) {
                        // 当t的左孩子的右子树根节点的balance = LEFT_HIGH
                        case LEFT_HEIGHT:
                            t.balance = RIGHT_HEIGHT;
                            tLeftChild.balance = EQUALS_HEIGHT;
                            tLeftChildRightChild.balance = EQUALS_HEIGHT;
                            break;
                        // 当t的左孩子的右子树根节点的balance = EQUAL_HIGH
                        case EQUALS_HEIGHT:
                            t.balance = EQUALS_HEIGHT;
                            tLeftChild.balance = EQUALS_HEIGHT;
                            tLeftChildRightChild.balance = EQUALS_HEIGHT;
                            break;
                        // 当t的左孩子的右子树根节点的balance = RIGHT_HIGH
                        case RIGHT_HEIGHT:
                            t.balance = EQUALS_HEIGHT;
                            tLeftChild.balance = LEFT_HEIGHT;
                            tLeftChildRightChild.balance = EQUALS_HEIGHT;
                            break;
                        default:
                            break;
                    }
                    // 先将t的左子树左旋
                    leftRotate(tLeftChild);
                    // 在将t右旋
                    rightRotate(t);
                    break;
                default:
                    break;
            }
        }
    
        /**
         * 右平衡操作,即结点t的不平衡是因为右子树过深
         *
         * @param t
         */
        private void rightBalance(Node<E> t) {
            if (t == null || t.right == null) {
                return;
            }
            Node<E> tRightChild = t.right;
            switch (tRightChild.balance) {
                // 如果新的结点插入到p的右孩子的左子树中,则需要进行分情况讨论
                case LEFT_HEIGHT:
                    Node<E> tRightChildLeftChild = tRightChild.left;
                    switch (tRightChildLeftChild.balance) {
                        case LEFT_HEIGHT:
                            t.balance = EQUALS_HEIGHT;
                            tRightChild.balance = RIGHT_HEIGHT;
                            tRightChildLeftChild.balance = EQUALS_HEIGHT;
                            break;
                        case EQUALS_HEIGHT:
                            t.balance = EQUALS_HEIGHT;
                            tRightChild.balance = EQUALS_HEIGHT;
                            tRightChildLeftChild.balance = EQUALS_HEIGHT;
                            break;
                        case RIGHT_HEIGHT:
                            t.balance = LEFT_HEIGHT;
                            tRightChild.balance = EQUALS_HEIGHT;
                            tRightChildLeftChild.balance = EQUALS_HEIGHT;
                            break;
                        default:
                            break;
                    }
                    // 先对t的右孩子进行右旋
                    rightRotate(tRightChild);
                    // 再对t进行左旋
                    leftRotate(t);
                    break;
                case EQUALS_HEIGHT:
                    break;
                // 如果新的结点插入到t的右孩子的右子树中,则直接进行左旋操作即可
                case RIGHT_HEIGHT:
                    t.balance = EQUALS_HEIGHT;
                    tRightChild.balance = EQUALS_HEIGHT;
                    leftRotate(t);
                    break;
                default:
                    break;
            }
        }
    
        /**
         * 左旋
         *
         * @param x 要旋转的节点
         */
        private void leftRotate(Node<E> x) {
            if (x == null || x.right == null) {
                return;
            }
            Node<E> y = x.right;
    
            // step 1
            x.right = y.left;
            if (y.left != null) {
                y.left.parent = x;
            }
    
            // step 2
            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;
            }
            y.parent = x.parent;
    
            // step 3
            y.left = x;
            x.parent = y;
        }
    
        /**
         * 右旋
         *
         * @param y 要旋转的节点
         */
        private void rightRotate(Node<E> y) {
            if (y == null || y.left == null) {
                return;
            }
            Node<E> x = y.left;
    
            // step 1
            y.left = x.right;
            if (x.right != null) {
                x.right.parent = y;
            }
    
            // step 2
            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;
            }
            x.parent = y.parent;
    
            // step 3
            x.right = y;
            y.parent = x;
        }
    
        public int getSize() {
            return size;
        }
    
        public Node<E> getRoot() {
            return root;
        }
    
        /**
         * 节点
         *
         * @param <E> 实现了Comparable接口
         */
        public class Node<E extends Comparable<E>> {
            /**
             * 数据
             */
            private E element;
            /**
             * 平衡因子
             */
            private int balance;
            /**
             * 左子树
             */
            private Node<E> left;
            /**
             * 右子树
             */
            private Node<E> right;
            /**
             * 父节点
             */
            private Node<E> parent;
    
            public Node(E element, Node<E> parent) {
                this.element = element;
                this.parent = parent;
            }
    
            public E getElement() {
                return element;
            }
    
            public void setElement(E element) {
                this.element = element;
            }
    
            public int getBalance() {
                return balance;
            }
    
            public void setBalance(int balance) {
                this.balance = balance;
            }
    
            public Node<E> getLeft() {
                return left;
            }
    
            public void setLeft(Node<E> left) {
                this.left = left;
            }
    
            public Node<E> getRight() {
                return right;
            }
    
            public void setRight(Node<E> right) {
                this.right = right;
            }
    
            public Node<E> getParent() {
                return parent;
            }
    
            public void setParent(Node<E> parent) {
                this.parent = parent;
            }
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值