zoukankan      html  css  js  c++  java
  • 二叉树 & 平衡二叉树 算法(Java实现)

    二叉树

    比如我要依次插入10、3、1、8、23、15、28。先插入10作为根节点:

     然后插入3,比10小,放在左边:

    再插入1,比10和3小,放在3左边:

    再插入8,比10小,比3大,放在3右边:

     再插入23,比10大,放在10右边:

     再插入15,比10大,比23小,放在23左边:

     最后插入28,比10和23大,放在23右边:

     代码实现:

    package com.demo.tree;
    
    import java.util.LinkedList;
    import java.util.Queue;
    
    
    public class BinaryTree {
    
        public static void main(String[] args){
            BinaryTree tree = new BinaryTree();
            tree.batchInsert(new int[]{10,3,1,8,23,15,28});
            tree.prePrint();
            tree.midPrint();
            tree.postPrint();
            tree.tierPrint();
            tree.printDepth();
        }
    
        private Node root;
    
        /**
         * 节点
         */
        private class Node{
            int data;   // 数据
            Node left;  // 左指针
            Node right; // 右指针
    
            private Node(int data) {
                this.data = data;
                this.left = null;
                this.right = null;
            }
        }
    
        /**
         * 插入
         * @param data
         */
        public void insert(int data){
            Node newData = new Node(data);
            if (root == null){
                root = newData;
            }else{
                Node parent = root;
                while (true){
                    if (data < parent.data){
                        // 如果左边为空,那新数据就直接放在这
                        if (parent.left == null){
                            parent.left = newData;
                            break;
                        }
                        // 进入左节点
                        parent = parent.left;
                    }else{
                        // 如果右边为空,那新数据就直接放在这
                        if (parent.right == null){
                            parent.right = newData;
                            break;
                        }
                        // 进入右节点
                        parent = parent.right;
                    }
                }
            }
        }
    
        /**
         * 批量插入
         * @param arr
         */
        public void batchInsert(int[] arr){
            for (int data : arr){
                insert(data);
            }
        }
    
        /**
         * 前序遍历
         */
        public void prePrint(){
            System.out.print("前序遍历	");
            if (root != null){
                pre(root);
            }
            System.out.println();
        }
    
        private void pre(Node node){
            if (node != null) {
                System.out.print(node.data + "	");
                pre(node.left);
                pre(node.right);
            }
        }
    
        /**
         * 中序遍历
         */
        public void midPrint(){
            System.out.print("中序遍历	");
            if (root != null){
                mid(root);
            }
            System.out.println();
        }
    
        private void mid(Node node){
            if (node != null) {
                mid(node.left);
                System.out.print(node.data + "	");
                mid(node.right);
            }
        }
    
        /**
         * 后序遍历
         */
        public void postPrint(){
            System.out.print("后序遍历	");
            if (root != null){
                post(root);
            }
            System.out.println();
        }
    
        private void post(Node node){
            if (node != null) {
                post(node.left);
                post(node.right);
                System.out.print(node.data + "	");
            }
        }
    
        /**
         * 层序遍历,利用队列先进先出
         */
        public void tierPrint(){
            if (root != null){
                Queue<Node> queue = new LinkedList<>();
                queue.add(root);
                System.out.print("层序遍历	");
                while (!queue.isEmpty()){
                    Node temp = queue.remove();
                    System.out.print(temp.data + "	");
                    if (temp.left != null){
                        // 左节点不为空,放进队列
                        queue.add(temp.left);
                    }
                    if (temp.right != null){
                        // 右节点不为空,放进队列
                        queue.add(temp.right);
                    }
                }
            }
            System.out.println();
        }
    
        /**
         * 求树高
         */
        public void printDepth(){
            if (root == null){
                System.out.println(0);
            }else{
                System.out.println("树高	" + getDepth(root));
            }
        }
    
        private int getDepth(Node node){
            if (node == null){
                return 0;
            }
            return Math.max(getDepth(node.left), getDepth(node.right))+1;
        }
    
    }

    测试:

     平衡二叉树

    前面的二叉树有个问题,如果我们按照顺序插入,那么这个树就会退化成一个线性链表,这个时候引入平衡二叉树来解决。

    平衡二叉树要维持平衡需要旋转操作

    LL型(在A的左孩子(L)的左子树(L)上插入新结点)

    过程:

    1. 将A的左孩子B提升为根节点

    2. 将A降级为B的右孩子

    3. 将B的右孩子调整为A的左孩子

    RR型(在A的右孩子(R)的右子树(R)上插入新结点)

    过程:

    1. 将A的右孩子B提升为根节点

    2. 将A降级为B的左孩子

    3. 将B的左孩子调整为A的右孩子

    LR型(在A的左孩子(L)的右子树(R)上插入新结点)【插入在C任意一颗子树都可以】

    过程:

    1. B、C节点左旋。

    2. A、C节点右旋。

    RL型(在A的右孩子(R)的左子树(L)上插入新结点)【插入在C任意一颗子树都可以】

    过程:

    1. B、C节点右旋。

    2. A、C节点左旋。

    插入步骤图解

    平衡二叉树的插入,例如依次插入:8,6,3,4,5,20,15,23,28,1,2

    插入8先作为根节点,插入6依然平衡,插入3不平衡,进行一次右旋(LL)

    插入4依然平衡,插入5不平衡,进行左旋(RR)

    插入20依然平衡,插入15不平衡,先右旋再左旋(RL)

    插入23依然平衡,插入28不平衡,进行一次左旋(RR)

    插入1依然平衡,插入2不平衡,先左旋再右旋(LR)

    代码

    package com.demo.tree;
    
    import java.util.LinkedList;
    import java.util.Queue;
    
    
    public class BalancedBinaryTree {
    
        public static void main(String[] args){
            BalancedBinaryTree tree = new BalancedBinaryTree();
            tree.batchInsert(new int[]{8,6,3,4,5,20,15,23,28,1,2});
            tree.tierPrint();
        }
    
        private Node root;
    
        /**
         * 节点
         */
        private class Node{
            int data;   // 数据
            Node left;  // 左指针
            Node right; // 右指针
    
            private Node(int data) {
                this.data = data;
                this.left = null;
                this.right = null;
            }
        }
    
        /**
         * 右旋操作(左孩子的左子树插入节点)
         * @param p
         */
        private Node rightRotate(Node p){
            Node temp = p.left;    // temp指向p的左子树
            p.left = temp.right;   // p的左子树指向temp的右子树
            temp.right = p;
            return temp;
        }
    
        /**
         * 左旋操作(右孩子的右子树插入节点)
         * @param p
         */
        private Node leftRotate(Node p){
            Node temp = p.right;    // temp指向p的右子树
            p.right = temp.left;   // p的右子树指向temp的左子树
            temp.left = p;
            return temp;
        }
    
        /**
         * 先左旋再右旋(左孩子的右子树插入节点)
         * @param p
         */
        private Node leftRightRotate(Node p){
            p.left = leftRotate(p.left);
            return rightRotate(p);
        }
    
        /**
         * 先右旋再左旋(右孩子的左子树插入节点)
         * @param p
         */
        private Node rightLeftRotate(Node p){
            p.right = rightRotate(p.right);
            return leftRotate(p);
        }
    
        /**
         * 树高
         * @param node
         * @return
         */
        private int getDepth(Node node){
            if (node == null){
                return 0;
            }
            return Math.max(getDepth(node.left), getDepth(node.right))+1;
        }
    
        /**
         * 平衡因子(左高:>1 等高:0 右高:<-1)
         * @return
         */
        public int balanceFactor(Node node){
            if (node == null){
                return 0;
            }
            return getDepth(node.left) - getDepth(node.right);
        }
    
        /**
         * 插入
         * @param node
         * @param data
         */
        public Node insert(Node node, int data){
            Node newData = new Node(data);
            if (node == null){
                return newData;
            }
            if (data < node.data){
                node.left = insert(node.left, data);
            }else if (data > node.data){
                node.right = insert(node.right, data);
            }else{
                return node;
            }
            int bf = balanceFactor(node);
    
            if (bf > 1 && data < node.left.data){
                // LL
                System.out.println("LL" + data);
                return rightRotate(node);
            }else if (bf < -1 && data > node.right.data){
                // RR
                System.out.println("RR" + data);
                return leftRotate(node);
            }else if (bf > 1 && data > node.left.data){
                // LR
                System.out.println("LR" + data);
                return leftRightRotate(node);
            }else if (bf < -1 && data < node.right.data){
                // RL
                System.out.println("RL" + data);
                return rightLeftRotate(node);
            }
            return node;
        }
    
        /**
         * 批量插入
         * @param arr
         */
        public void batchInsert(int[] arr){
            for (int data : arr){
                root = insert(root, data);
            }
        }
    
        /**
         * 前序遍历
         */
        public void prePrint(){
            System.out.print("前序遍历	");
            if (root != null){
                pre(root);
            }
            System.out.println();
        }
    
        private void pre(Node node){
            if (node != null) {
                System.out.print(node.data + "	");
                pre(node.left);
                pre(node.right);
            }
        }
    
        /**
         * 中序遍历
         */
        public void midPrint(){
            System.out.print("中序遍历	");
            if (root != null){
                mid(root);
            }
            System.out.println();
        }
    
        private void mid(Node node){
            if (node != null) {
                mid(node.left);
                System.out.print(node.data + "	");
                mid(node.right);
            }
        }
    
        /**
         * 后序遍历
         */
        public void postPrint(){
            System.out.print("后序遍历	");
            if (root != null){
                post(root);
            }
            System.out.println();
        }
    
        private void post(Node node){
            if (node != null) {
                post(node.left);
                post(node.right);
                System.out.print(node.data + "	");
            }
        }
    
        /**
         * 层序遍历,利用队列先进先出
         */
        public void tierPrint(){
            if (root != null){
                Queue<Node> queue = new LinkedList<>();
                queue.add(root);
                System.out.print("层序遍历	");
                while (!queue.isEmpty()){
                    Node temp = queue.remove();
                    System.out.print(temp.data + "	");
                    if (temp.left != null){
                        // 左节点不为空,放进队列
                        queue.add(temp.left);
                    }
                    if (temp.right != null){
                        // 右节点不为空,放进队列
                        queue.add(temp.right);
                    }
                }
            }
        }
    
    }
  • 相关阅读:
    新词发现
    隐马尔可夫模型
    nodejs命令行解析工具之minimist
    react 生命周期
    react 中的 super super(props)
    object 常用方法总结
    前端安全 中间人攻击
    Postgresql的临时表的用法
    windows下postgresql数据库备份和还原
    PostgreSQL 数据库开发规范——命名规范 & 设计规范
  • 原文地址:https://www.cnblogs.com/LUA123/p/11820757.html
Copyright © 2011-2022 走看看