zoukankan      html  css  js  c++  java
  • 数据结构——二叉树遍历之“递归与非递归遍历”

    简述

    二叉树的遍历分为先序遍历、中序遍历和后序遍历。如下图所示:

    递归遍历

    private void bianli1(List<Integer> list, TreeNode root) {
        // 先序遍历
        if (root == null) {
            return;
        }
        list.add(root.val);
        bianli1(list, root.left);
        bianli1(list, root.right);
    }
    
    private void bianli2(List<Integer> list, TreeNode root) {
        // 中序遍历
        if (root == null) {
            return;
        }
        bianli2(list, root.left);
        list.add(root.val);
        bianli2(list, root.right);
    }
    
    private void bianli3(List<Integer> list, TreeNode root) {
        // 后序遍历
        if (root == null) {
            return;
        }
        bianli3(list, root.left);
        bianli3(list, root.right);
        list.add(root.val);
    }

    递归遍历实现比较简单,递归利用函数栈来保存信息。

    非递归遍历

    非递归需要额外自己申请数据结构来代替函数栈。

    先序遍历:

    1.申请一个栈 stack。然后将头结点 head 压入 stack 中。
    2.从 stack 中弹出栈顶结点,记为 cur,然后打印 cur 结点的值,再将 cur 的右孩子(非空的话)和左孩子(非空的话)分别压入栈中。
    3.不断重复步骤 2,直到栈 stack 为空,全部过程结束。

    中序遍历:

    1.申请一个栈 stack。初始时,令变量 cur=head。
    2.先把 cur 结点压入栈中,然后依次把左边界压入栈中,即不停的令 cur=cur.left,重复该步骤。
    3.不断重复步骤 2,直到 cur 为空为止,此时从 stack 中弹出栈顶元素,记为 node。打印 node 的值,并将 cur=node.right,然后继续重复步骤2。
    4.当 stack 为空且 cur 为空时,整个过程停止。

    后序遍历:

    1.申请一个栈,记为s1,然后将头结点 head 压入 s1 中。
    2.从 s1 中弹出的结点记为 cur,然后依次将 cur 的左孩子和右孩子压入 s1 中。
    3.整个过程中 s1 所弹出的结点都压入 s2 中。
    4.不断重复步骤2-3,直到 s1 为空为止。
    5.从 s2 中弹出结点并打印,打印的顺序就是后序遍历的顺序。

    源码实现:

    /**
     * 先序遍历
     */
    private static void xianxu(List<Integer> list, TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        stack.add(root);
        while (!stack.isEmpty()) {
            root = stack.pop();
            list.add(root.val);
            if (root.right != null) {
                stack.push(root.right);
            }
            if (root.left != null){
                stack.push(root.left);
            }
    
        }
    }
    /**
     * 中序遍历
     */
    private static void zhongxu(List<Integer> list, TreeNode root) {
        Stack<TreeNode> stack = new Stack<TreeNode>();
        while (!stack.isEmpty() || root!=null) {
            if (root != null) {
                stack.push(root);
                root = root.left;
            }else {
                root = stack.pop();
                list.add(root.val);
                root = root.right;
            }
        }
    }
    /**
     * 后序遍历
     */
    private static void houxu(List<Integer> list, TreeNode root) {
        Stack<TreeNode> stack1 = new Stack<TreeNode>();
        Stack<TreeNode> stack2 = new Stack<TreeNode>();
        stack1.add(root);
        while (!stack1.isEmpty()) {
            root = stack1.pop();
            stack2.push(root);
            if (root.left != null) {
                stack1.push(root.left);
            }
            if (root.right != null) {
                stack1.push(root.right);
            }
        }
        while (!stack2.isEmpty()) {
            list.add(stack2.pop().val);
        }
    }

    参考资料

    [1] 程序员代码面试, 第三章 - 二叉树问题

  • 相关阅读:
    Attach Files to Objects 将文件附加到对象
    Provide Several View Variants for End-Users 为最终用户提供多个视图变体
    Audit Object Changes 审核对象更改
    Toggle the WinForms Ribbon Interface 切换 WinForms 功能区界面
    Change Style of Navigation Items 更改导航项的样式
    Apply Grouping to List View Data 将分组应用于列表视图数据
    Choose the WinForms UI Type 选择 WinForms UI 类型
    Filter List Views 筛选器列表视图
    Make a List View Editable 使列表视图可编辑
    Add a Preview to a List View将预览添加到列表视图
  • 原文地址:https://www.cnblogs.com/zhengbin/p/6569068.html
Copyright © 2011-2022 走看看