平衡二叉树-Java

AVL是最先发明的自平衡二叉查找树算法。在AVL中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树,n个结点的AVL树最大深度约1.44log2n。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

package com.gloomy.Tree;

import java.util.ArrayDeque;
import java.util.Queue;
import java.util.Stack;

/**
 * 平衡二叉树
 * 
 * @author 过路的守望
 *
 */
public class AVLTree {

    /*
     * 平衡二叉树的更
     */
    private Node root;

    public AVLTree(Node root) {
        this.root = root;
    }

    public static void main(String[] args) {
        Node A = new Node(1);
        Node B = new Node(2);
        Node C = new Node(3);
        Node D = new Node(4);
        Node E = new Node(5);
        Node F = new Node(6);
        Node G = new Node(7);
        Node H = new Node(8);
        Node I = new Node(9);
        Node J = new Node(10);
        Node K = new Node(11);
        Node L = new Node(12);
        Node M = new Node(13);
        Node N = new Node(14);
        AVLTree avlTree = new AVLTree(C);
        avlTree.insert(D);
        avlTree.insert(E);
        avlTree.insert(A);
        avlTree.insert(B);
        avlTree.insert(F);
        avlTree.insert(G);
        avlTree.insert(M);
        avlTree.insert(N);
        avlTree.insert(J);
        avlTree.insert(H);
        avlTree.insert(I);
        avlTree.insert(K);
        avlTree.insert(L);
        avlTree.remove(G);
        avlTree.remove(M);
        avlTree.remove(E);
        avlTree.remove(F);
        avlTree.remove(D);
        avlTree.remove(I);
        avlTree.remove(J);
        System.out.println(avlTree.findMax().val);
        System.out.println(avlTree.findMin().val);
        avlTree.levelOrder(avlTree.root);
        avlTree.preOrder(avlTree.root);
        avlTree.inOrder(avlTree.root);
        avlTree.postOrder(avlTree.root);
    }

    /**
     * 平衡二叉树中是否包含节点node
     * 
     * @param node
     * @return
     */
    public boolean contains(Node node) {
        /*
         * 平衡二叉树为空,自然不包含
         */
        if (root == null) {
            return false;
        }
        Node currentNode = root;
        /*
         * 标记node是否大于当前节点
         */
        int flag = node.compareTo(currentNode);
        /*
         * 检查平衡二叉树中是否包含节点node
         */
        while (flag != 0) {
            if (flag > 0) {
                currentNode = currentNode.right;
            } else {
                currentNode = currentNode.left;
            }
            /*
             * 平衡二叉树树中为找到节点node,放回false。
             */
            if (currentNode == null) {
                return false;
            }
            flag = node.compareTo(currentNode);
        }
        return true;
    }

    /**
     * 递归检查平衡二叉树中root是否包含node节点
     * 
     * @param node
     * @param root
     */
    public boolean contains(Node node, Node root) {
        /*
         * root为空显然不包含节点node
         */
        if (root == null) {
            return false;
        }
        int flag = node.compareTo(root);
        /*
         * 在root的右子树中检查是否含有node节点
         */
        if (flag > 0) {
            return contains(node, root.right);
        }
        /*
         * 在root的左子树中检查是否含有node节点
         */
        if (flag < 0) {
            return contains(node, root.left);
        }
        /*
         * root中含有此节点,返回true
         */
        return true;
    }

    /**
     * 返回平衡二叉树中的最大节点
     * 
     * @return
     */
    public Node findMax() {

        return findMax(root);
    }

    /**
     * 返回平衡二叉树中的最小节点
     * 
     * @return
     */
    public Node findMin() {
        return findMin(root);
    }

    /**
     * 找到平衡二叉树root中的最大节点
     * 
     * @param root
     * @return
     */
    private Node findMax(Node root) {
        /**
         * root节点为空
         */
        if (root == null) {
            return null;
        }
        /*
         * 找到右子树中的最大元素节点
         */
        Node currentNode = root;
        while (currentNode.right != null) {
            currentNode = currentNode.right;
        }
        return currentNode;
    }

    /**
     * 递归查找平衡二叉树中的最大节点
     * 
     * @param root
     * @return
     */
    private Node findMaxRec(Node root) {
        if (root == null) {
            return null;
        }
        if (root.right != null) {
            return findMaxRec(root.right);
        }
        return root;
    }

    /**
     * 查找平衡二叉树root中的最小节点
     * 
     * @param node
     * @param root
     * @return
     */
    private Node findMin(Node root) {
        /*
         * root为空
         */
        if (root == null) {

        }
        /*
         * 在左子树中寻找最小节点元素
         */
        Node currentNode = root;
        while (currentNode.left != null) {
            currentNode = currentNode.left;
        }
        return currentNode;
    }

    /**
     * 递归查找平衡二叉树中的最小元素
     * 
     * @param root
     * @return
     */
    private Node findMinRec(Node root) {
        /*
         * root 为空
         */
        if (root == null) {
            return root;
        }
        if (root.left != null) {
            return findMinRec(root.left);
        }
        return root;
    }

    /**
     * 返回节点node的高度,node如果为null,则高度为-1
     * 
     * @param node
     * @return
     */
    private int getHeight(Node node) {
        return node == null ? -1 : node.hight;
    }

    /**
     * 单旋转-右旋
     * 
     * @param node
     * @return
     */
    private Node rolateWithLeftChild(Node node) {
        Node leftChild = node.left;
        node.left = leftChild.right;
        leftChild.right = node;
        /*
         * 更新节点高度
         */
        node.hight = 1 + Math.max(getHeight(node.left), getHeight(node.right));
        leftChild.hight = 1 + Math.max(getHeight(leftChild.left),
                getHeight(leftChild.right));
        return leftChild;

    }

    /**
     * 单旋转-左旋
     * 
     * @param node
     * @return
     */
    private Node rolateWithRightChild(Node node) {
        Node rightChild = node.right;
        node.right = rightChild.left;
        rightChild.left = node;
        /*
         * 更新节点高度
         */
        node.hight = 1 + Math.max(getHeight(node.left), getHeight(node.right));
        rightChild.hight = 1 + Math.max(getHeight(rightChild.left),
                getHeight(rightChild.right));
        return rightChild;
    }

    /**
     * 双旋转-RL
     * 
     * @param node
     * @return
     */
    private Node doubleWithLeftChild(Node node) {
        node.left = rolateWithRightChild(node.left);
        return rolateWithLeftChild(node);
    }

    /**
     * 双旋转-LR
     * 
     * @param node
     * @return
     */
    private Node doubleWithRightChild(Node node) {
        node.right = rolateWithLeftChild(node.right);
        return rolateWithRightChild(node);
    }

    /**
     * 向平衡二叉树中插入节点node
     * 
     * @param node
     */
    public void insert(Node node) {
        /*
         * 更新引用(传值)
         */
        root = insert(node, root);
    }

    /**
     * 删除平衡二叉树中的节点node
     * 
     * @param node
     */
    public void remove(Node node) {
        root = remove(node, root);
    }

    /**
     * 递归实现向root平衡二叉树中插入元素node
     * 
     * @param node
     * @param root
     * @return
     */
    private Node insert(Node node, Node root) {
        if (root == null) {
            root = new Node(node.val);
        }
        int flag = node.compareTo(root);
        if (flag > 0) {
            root.right = insert(node, root.right);
            /*
             * 左右子树高度差
             */
            flag = Math.abs(getHeight(root.left) - getHeight(root.right));
            if (flag == 2) {
                /*
                 * RR型
                 */
                if (getHeight(root.right.right) > getHeight(root.right.left)) {
                    root = rolateWithRightChild(root);
                }
                /*
                 * RL型
                 */
                else {
                    root = doubleWithRightChild(root);
                }
            }
        } else if (flag < 0) {
            root.left = insert(node, root.left);
            /*
             * 左右子树高度差
             */
            flag = Math.abs(getHeight(root.left) - getHeight(root.right));
            if (flag == 2) {
                /*
                 * LL型
                 */
                if (getHeight(root.left.left) > getHeight(root.left.right)) {
                    root = rolateWithLeftChild(root);
                }
                /*
                 * LR型
                 */
                else {
                    root = doubleWithLeftChild(root);
                }
            }
        }
        /*
         * 更新root的高度 上层的高度由子树的高度决定
         */
        root.hight = 1 + Math.max(getHeight(root.left), getHeight(root.right));
        return root;
    }

    /**
     * 递归删除二叉平衡树root中的节点node
     * 
     * @param node
     * @param root
     * @return
     */
    private Node remove(Node node, Node root) {
        /*
         * root为空
         */
        if (root == null) {
            return null;
        }
        int flag = node.compareTo(root);
        /*
         * 待删除节点在右子树上
         */
        if (flag > 0) {
            root.right = remove(node, root.right);
        }
        /*
         * 待删除节点在左子树上
         */
        if (flag < 0) {
            root.left = remove(node, root.left);
        }
        /*
         * 找到待删除节点
         */
        if (flag == 0) {
            if (root.left != null && root.right != null) {
                /*
                 * 用待删除节点右子树上的最小节点的与待删除节点交换,然后问题变为删除节点replaceNode
                 */
                Node replaceNode = findMin(root.right);
                root.val = replaceNode.val;
                root.right = remove(replaceNode, root.right);
            } else {
                root = root.right == null ? root.left : root.right;
            }
        }
        if (root != null) {
            flag = Math.abs(getHeight(root.left) - getHeight(root.right));
        } else {
            flag = 0;
        }
        if (flag == 2) {
            if (getHeight(root.left) > getHeight(root.right)) {
                /*
                 * LL型旋转
                 */
                if (getHeight(root.left.left) > getHeight(root.left.right)) {
                    root = rolateWithLeftChild(root);
                }
                /*
                 * LR型旋转
                 */
                else {
                    root = doubleWithLeftChild(root);
                }
            } else {
                /*
                 * RR型旋转
                 */
                if (getHeight(root.right.right) > getHeight(root.right.left)) {
                    root = rolateWithRightChild(root);
                }
                /*
                 * RL型旋转
                 */
                else {
                    root = doubleWithRightChild(root);
                }
            }
        }
        /*
         * 更新root的高度
         */
        if (root != null) {
            root.hight = 1 + Math.max(getHeight(root.left),
                    getHeight(root.right));
        }
        return root;
    }

    /**
     * 非递归先序遍历
     * 
     * @param node
     */
    public void preOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println("先序遍历:");
        Stack<Node> stack = new Stack<Node>();
        stack.push(node);
        while (!stack.isEmpty()) {
            node = stack.pop();
            System.out.print(node.val + " ");
            /*
             * 先加入右儿子
             */
            if (node.right != null) {
                stack.push(node.right);
            }
            if (node.left != null) {
                stack.push(node.left);
            }
        }
        System.out.println();
    }

    /**
     * 非递归中序遍历
     * 
     * @param node
     */
    public void inOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println("中序遍历:");
        Stack<Node> stack = new Stack<Node>();
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                stack.push(node);
                node = node.left;
            }
            /*
             * 处理完左子树,根节点,处理右子树。
             */
            node = stack.pop();
            System.out.print(node.val + " ");
            node = node.right;
        }
        System.out.println();
    }

    /**
     * 非递归后序遍历
     * 
     * @param node
     */
    public void postOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println("后序遍历:");
        Stack<Node> stack = new Stack<Node>();
        /*
         * preNode记录前一个出栈的节点
         */
        Node preNode = null;
        while (node != null || !stack.isEmpty()) {
            while (node != null) {
                stack.push(node);
                node = node.left;
            }
            node = stack.peek();
            /*
             * 处理完左子树,在处理右子树,最后处理根节点。
             */
            while (node.right == null || node.right == preNode) {
                System.out.print(node.val + " ");
                stack.pop();
                preNode = node;
                if (stack.isEmpty()) {
                    System.out.println();
                    return;
                }
                node = stack.peek();
            }
            node = node.right;
        }
    }

    public void levelOrder(Node node) {
        if (node == null) {
            return;
        }
        System.out.println("层序遍历:");
        Queue<Node> queue = new ArrayDeque<Node>();
        queue.offer(node);
        /*
         * 处理完上一层厚再处理下一层
         */
        while (!queue.isEmpty()) {
            node = queue.poll();
            System.out.print(node.val + " ");
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
        System.out.println();
    }

}

/**
 * 平衡二叉树节点类
 * 
 * @author 过路的守望
 */
class Node implements Comparable<Node> {
    /*
     * val 节点值 height 节点高度
     */
    int val;
    Node left;
    Node right;
    int hight;

    public Node(int val) {
        this.val = val;
    }

    @Override
    public int compareTo(Node o) {
        return this.val - o.val;
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值