数据结构 | 二叉树

概念辨析

遍历逻辑

  • DFS:前中后序遍历的逻辑可以借助栈使用递归的方式
  • BFS:一般使用队列来实现(先进先出)

解题模式

参考源

  1. 是否可以通过遍历一遍二叉树得到答案?如果可以,用一个traverse函数配合外部遍历来实现 ————「遍历」思维模式
  2. 是否可以定义一个递归函数,通过子问题(子树)的答案推导出原问题的答案?如果可以,写出这个递归函数的定义,并充分利用这个函数的返回值,————「分解问题」思维模式

如果单独抽出一个二叉树节点,它需要做什么事情?需要在什么时候(前/中/后序位置)做?其他的节点无需操心,递归函数会帮你在所有节点上执行相同的操作。

二叉树的所有问题,就是让你在前中后序位置注入巧妙的代码逻辑,去达到自己的目的,你只需要单独思考每一个节点应该做什么,其他的不用你管,抛给二叉树遍历框架,递归会在所有节点上做相同的操作

二叉树递归模板

    void traverse(TreeNode root) {
        if (root == null) {
            return;
        }

        // 前序位置
        traverse(root.left);
        // 中序位置
        traverse(root.right);
        // 后序位置

    }

主类

节点是组成部件,树构建节点之间的逻辑关系。不管是树结构也好,还是链表结构也好,头部节点是寻找整个结构最至关重要的部件,是访问的入口,链表最重要的就是头结点,数组也是。

public class TreeNode<T> {

    T val;
    TreeNode<T> left;
    TreeNode<T> right;

    TreeNode(T value) {
        this.val = value;
        this.left = null;
        this.right = null;
    }
}

前序/中序/后序

public class BinaryTree<T extends Comparable<T>> {

    private TreeNode<T> root;

    public BinaryTree() {
        this.root = null;
    }

    public void insert(T value) {
        if (null == root) {
            root = new TreeNode<>(value);
        }  else {
            // TODO insertRecursive(root,value)
            insertRecursive(root,value);
        }

    }

    /**
     * 随机插入节点
     * @param currentNode
     * @param value
     */
    private void insertInto(TreeNode<T> currentNode, T value) {
        if (Math.random() < 0.5) {
            if (currentNode.left == null) {
                currentNode.left = new TreeNode<>(value);
            } else {
                insertInto(currentNode.left, value);
            }
        } else {
            if (currentNode.right == null) {
                currentNode.right = new TreeNode<>(value);
            } else {
                insertInto(currentNode.right, value);
            }
        }
    }


    /**
     * 递归插入 二叉搜索树
     * @param currentNode
     * @param value
     */
    private void insertRecursive(TreeNode<T> currentNode, T value) {
        if (value.compareTo(currentNode.val) < 0) {
            if (currentNode.left == null) {
                currentNode.left = new TreeNode<>(value);
            } else {
                insertRecursive(currentNode.left, value);
            }
        } else {
            if (currentNode.right == null) {
                currentNode.right = new TreeNode<>(value);
            } else {
                insertRecursive(currentNode.right, value);
            }
        }

    }


    /**
     * 递归先序遍历
     */
    public void preorderTraversal() {
        // TODO preorderTraversalRecursive(root)
        preorderTraversalRecursive(root);
    }

    private void preorderTraversalRecursive(TreeNode<T> node) {
        if (null != node) {
            System.out.print(node.val + "   ");
            preorderTraversalRecursive(node.left);
            preorderTraversalRecursive(node.right);
        }
    }


    /**
     * 递归中序遍历
     */
    public void inorderTraversal() {
        // TODO inorderTraversalRecursive(root)
        inorderTraversalRecursive(root);
    }

    private void inorderTraversalRecursive(TreeNode<T> node) {
        if (null != node) {
            inorderTraversalRecursive(node.left);
            System.out.print(node.val + "   ");
            inorderTraversalRecursive(node.right);
        }
    }

    /**
     * 递归后序遍历
     */
    public void postorderTraversal() {
        // TODO postorderTraversalRecursive(root)
        postorderTraversalRecursive(root);
    }

    private void postorderTraversalRecursive(TreeNode<T> node) {
        if (null != node) {
            postorderTraversalRecursive(node.left);
            postorderTraversalRecursive(node.right);
            System.out.print(node.val + "   ");
        }
    }

    /**
     * 迭代前序遍历
     */
    public void iterativePreorderTraversal() {
        Stack<TreeNode<T>> stack = new Stack<>();
        TreeNode<T> current = root;

        while (current != null || !stack.isEmpty()) {
            while (current != null) {
                System.out.print(current.val + "   ");
                stack.push(current);
                current = current.left;
            }

            current = stack.pop();
            current = current.right;
        }
    }

    /**
     * 迭代中序遍历
     */
    public void iterativeInorderTraversal() {
        Stack<TreeNode<T>> stack = new Stack<>();
        TreeNode<T> current = root;

        while (current != null || !stack.isEmpty()) {
            while (current != null) {
                stack.push(current);
                current = current.left;
            }

            current = stack.pop();
            System.out.print(current.val + "   ");
            current = current.right;
        }
    }


    /**
     * 迭代后序遍历
     */
    public void iterativePostorderTraversal() {
        Stack<TreeNode<T>> stack1 = new Stack<>();
        Stack<TreeNode<T>> stack2 = new Stack<>();
        TreeNode<T> current = root;

        if (current != null) {
            stack1.push(current);
        }

        while (!stack1.isEmpty()) {
            current = stack1.pop();
            stack2.push(current);

            if (current.left != null) {
                stack1.push(current.left);
            }

            if (current.right != null) {
                stack1.push(current.right);
            }
        }

        while (!stack2.isEmpty()) {
            System.out.print(stack2.pop().val + "   ");
        }
    }
}

测试类

public class BinaryTreeTest {

    @Test
    public void test_BinaryTree() {
        BinaryTree<Integer> tree = new BinaryTree<>();
        tree.insert(10);
        tree.insert(5);
        tree.insert(15);
        tree.insert(3);
        tree.insert(7);
        tree.insert(12);
        tree.insert(18);

        System.out.println("Preorder traversal: ");
        tree.preorderTraversal();
        System.out.println();

        System.out.println("Iterative Preorder traversal: ");
        tree.iterativePreorderTraversal();
        System.out.println();

        System.out.println("====================================");

        System.out.println("Inorder traversal: ");
        tree.inorderTraversal();
        System.out.println();

        System.out.println("Iterative Inorder traversal");
        tree.iterativeInorderTraversal();
        System.out.println();

        System.out.println("====================================");

        System.out.println("Postorder traversal: ");
        tree.postorderTraversal();
        System.out.println();

        System.out.println("Iterative Postorder traversal");
        tree.iterativePostorderTraversal();
        System.out.println();

    }
}

posted @ 2024-08-12 13:34  Neking  阅读(5)  评论(0编辑  收藏  举报