二叉树的遍历、查找、插入、删除等

/********************************************
 * All Rights Reserved By www.laughing.ren
 * @author:Laughing_Lz
 * @version:2018年11月29日 下午11:33:24
 * ******************************************/
package ren.laughing.code.Test;

import java.util.LinkedList;
import java.util.Queue;

/**
 * 二叉树
 * 
 * @author Laughing_Lz
 *
 */
public class Tree {

    /**
     * 前序遍历二叉树
     * 
     * @param root
     */
    public static void preOrder(Node root{
        if (root == null) {
            return;
        }
        System.out.print(root.getValue() + " ");
        if (root.getLeft() != null) {
            preOrder(root.getLeft());
        }
        if (root.getRight() != null) {
            preOrder(root.getRight());
        }
    }

    /**
     * 中序遍历二叉树
     * 
     * @param root
     */
    public static void inOrder(Node root{
        if (root == null) {
            return;
        }
        if (root.getLeft() != null) {
            inOrder(root.getLeft());
        }
        System.out.print(root.getValue() + " ");
        if (root.getRight() != null) {
            inOrder(root.getRight());
        }
    }

    /**
     * 后序遍历二叉树
     * 
     * @param root
     */
    public static void postOrder(Node root{
        if (root == null) {
            return;
        }
        if (root.getLeft() != null) {
            postOrder(root.getLeft());
        }
        if (root.getRight() != null) {
            postOrder(root.getRight());
        }
        System.out.print(root.getValue() + " ");
    }

    /**
     * 层次遍历二叉树
     * 
     * @param root
     */
    public static void levelOrder(Node root{
        if (root == null) {
            return;
        }
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(root);
        while (!queue.isEmpty()) {
            Node currentNode = queue.poll();
            System.out.print(currentNode.getValue() + " ");
            if (currentNode.getLeft() != null) {
                queue.add(currentNode.getLeft());
            }
            if (currentNode.getRight() != null) {
                queue.add(currentNode.getRight());
            }
        }
    }

    /**
     * 卡特兰数: 给定一组数据,比如 1,3,5,6,9,10。你来算算,可以构建出多少种不同的二叉树?
     * https://en.wikipedia.org/wiki/Catalan_number
     * 
     * @param numKeys
     * @return
     */
    public static int countTrees(int numKeys{
        if (numKeys <= 1) {
            return (1);
        } else {
            int sum = 0;
            int left, right, root;
            // 每次迭代,root节点的左右两颗子树的节点数不同--左子树的节点数从0到numKeys-1,右子树相反
            // 这样迭代结束后,各种情况便都覆盖全了;
            for (root = 1; root <= numKeys; root++) {
                left = countTrees(root - 1);
                right = countTrees(numKeys - root);

                // number of possible trees with this root == left*right
                sum += left * right;
            }
            return (sum);
        }
    }

    static class Node {
        private int value;
        private Node left;
        private Node right;

        public Node(int value{
            super();
            this.value = value;
        }

        public Node() {
            super();
        }

        public Node getLeft() {
            return left;
        }

        public void setLeft(Node left{
            this.left = left;
        }

        public Node getRight() {
            return right;
        }

        public void setRight(Node right{
            this.right = right;
        }

        public void setValue(int value{
            this.value = value;
        }

        public int getValue() {
            return this.value;
        }
    }

    /**
     * 二叉查找树的查找操作 二叉查找树:每个节点的左节点都比当前节点值小,右节点都比当前节点大值。
     * 
     * @param root
     * @param value
     * @return
     */
    public static Node find(Node root, int value{
        if (root == null) {
            return null;
        }
        while (root != null) {
            if (root.getValue() == value) {
                return root;
            } else if (root.getValue() > value) {
                root = root.getLeft();
            } else if (root.getValue() < value) {
                root = root.getRight();
            }
        }
        return null;
    }

    /**
     * 二叉查找树的插入操作
     * 
     * @param root
     * @param value
     */
    public static void insert(Node root, int value{
        if (root == null) {
            root = new Node(value);
        }
        while (root != null) {
            if (root.getValue() < value) {
                if (root.getRight() == null) {
                    root.setRight(new Node(value));
                    return;
                }
                root = root.getRight();
            } else if (root.getValue() > value) {
                if (root.getLeft() == null) {
                    root.setLeft(new Node(value));
                    return;
                }
                root = root.getLeft();
            }
        }
    }

    /**
     * 二叉查找树的删除操作,要注意有三种情况:1、待删除节点没有子节点2、待删除节点只有一个子节点(只需更新父节点)
     * 3、待删除节点有两个子节点(从待删除节点的左子节点中找出最大的节点替换,或从右子节点中找出最小的节点替换)
     * 
     * @param tree
     * @param data
     */
    public static void delete(Node tree, int data{
        Node p = tree; // p 指向要删除的节点,初始化指向根节点
        Node pp = null// pp 记录的是 p 的父节点
        while (p != null && p.getValue() != data) {
            pp = p;
            if (data > p.getValue())
                p = p.right;
            else
                p = p.left;
        }
        if (p == null)
            return// 没有找到

        // 要删除的节点有两个子节点
        if (p.left != null && p.right != null) { // 查找右子树中最小节点
            Node minP = p.right;
            Node minPP = p; // minPP 表示 minP 的父节点
            while (minP.left != null) {
                minPP = minP;
                minP = minP.left;
            }
            p.setValue(minP.getValue()); // 将 minP 的数据替换到 p 中
            p = minP; // 下面就变成了删除 minP 了
            pp = minPP;
        }

        // 删除节点是叶子节点或者仅有一个子节点
        Node child; // p 的子节点
        if (p.left != null)
            child = p.left;
        else if (p.right != null)
            child = p.right;
        else
            child = null;

        if (pp == null)
            tree = child; // 删除的是根节点
        else if (pp.left == p)
            pp.left = child;
        else
            pp.right = child;

        System.out.println("\n删除节点" + data + "后:");
        inOrder(tree);
    }

    /**
     * 计算二叉树的高度
     *
     * @param root
     * @param index
     * @return
     */
    public static int getBinaryLevel(Node root, int index{
        if (null == root) {
            return index;
        }

        int maxleftLevel = 0;
        if (root.left != null) {
            maxleftLevel = getBinaryLevel(root.left, index + 1);
        }

        int maxRightLevel = 0;

        if (root.right != null) {
            maxRightLevel = getBinaryLevel(root.right, index + 1);
        }

        return Math.max(maxleftLevel, maxRightLevel) + 1;
    }

    public static void main(String[] args{
        // 构建二叉树
        Node leaf1 = new Node(6);
        Node leaf2 = new Node(9);
        Node leaf3 = new Node(10);
        Node node1 = new Node(3);
        node1.setLeft(leaf1);
        node1.setRight(leaf2);
        Node node2 = new Node(5);
        node2.setLeft(leaf3);
        Node root = new Node(1);
        root.setLeft(node1);
        root.setRight(node2);
        // 构建中序遍历有序的二叉查找树
        Node leaf11 = new Node(1);
        Node leaf22 = new Node(5);
        Node leaf33 = new Node(9);
        Node node11 = new Node(3);
        node11.setLeft(leaf11);
        node11.setRight(leaf22);
        Node node22 = new Node(10);
        node22.setLeft(leaf33);
        Node root1 = new Node(6);
        root1.setLeft(node11);
        root1.setRight(node22);

        System.out.println("前序遍历:");
        preOrder(root);
        System.out.println("\n中序遍历:");
        inOrder(root);
        System.out.println("\n后序遍历:");
        postOrder(root);
        System.out.println("\n层次遍历:");
        levelOrder(root);
        System.out.print("\n计算卡特兰数:\n" + countTrees(3));
        System.out.print("\n二叉查找树的查找操作:\n" + find(root1, 6).value);
        System.out.print("\n计算二叉树高度:\n" + getBinaryLevel(root, 0));
        System.out.println("\n二叉查找树的插入操作:");
        insert(root1, 11);
        System.out.println("\n二叉查找树插入节点11后:");
        inOrder(root1);
        System.out.println("\n二叉查找树的删除操作:");
        delete(root1, 6);
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注