数据结构——二叉树遍历之“递归与非递归遍历”

简述

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

递归遍历

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] 程序员代码面试, 第三章 - 二叉树问题

时间: 2024-12-26 09:31:59

数据结构——二叉树遍历之“递归与非递归遍历”的相关文章

数据结构二叉树的递归与非递归遍历之 实现可编译(1)java

前一段时间,学习数据结构的各种算法,概念不难理解,只是被C++的指针给弄的犯糊涂,于是用java,web,javascript,分别去实现数据结构的各种算法. 二叉树的遍历,本分享只是以二叉树中的先序遍历为例进行说明,中序遍历和后序遍历,以此类推! 二叉树递归与非递归遍历的区别,虽然递归遍历,跟容易读懂,代码量少,运算快,但是却容易出现溢出的问题,所以所以非递归遍历,在处理千万级的运算量时会先的很有用处. 二叉树的先序遍历:先访问根节点,再访问先后访问左右节点.如图: 二叉树的递归遍历之java

Java数据结构系列之——树(4):二叉树的中序遍历的递归与非递归实现

package tree.binarytree; import java.util.Stack; /** * 二叉树的中序遍历:递归与非递归实现 * * @author wl * */ public class BiTreeInOrder { // 中序遍历的递归实现 public static void biTreeInOrderByRecursion(BiTreeNode root) { if (root == null) { return; } biTreeInOrderByRecursi

Java数据结构系列之——树(5):二叉树的后序遍历的递归与非递归实现

package tree.binarytree; import java.util.Stack; /** * 二叉树后序遍历的递归与非递归实现 * * @author wl * */ public class BitreePostOrder { // 后序遍历的递归实现 public static void biTreePostOrderByRecursion(BiTreeNode root) { if (root == null) { return; } biTreePostOrderByRe

二叉树的前序、中序、后序遍历(递归、非递归)实现

本文部分来源于CSDN兰亭风雨大牛的原创.链接为http://blog.csdn.net/ns_code/article/details/12977901 二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的.二叉树有前.中.后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但其开销也比较大,而若采用非递归方法实现三种遍历,则要用栈来模拟实现(递归也是用栈实现的).下面先简要介绍三种遍历方式的递归实现,再详细介绍三种遍

C实现二叉树(模块化集成,遍历的递归与非递归实现)

C实现二叉树模块化集成 实验源码介绍(源代码的总体介绍):header.h : 头文件链栈,循环队列,二叉树的结构声明和相关函数的声明.LinkStack.c : 链栈的相关操作函数定义.Queue.c : 循环队列的相关操作函数定义.BinTree.c : 二叉树的相关操作的函数定义,层序序列生成二叉树,二叉树的前序序列.中序序列.后序序列的递归和非递归实现,求叶子结点的递归与非递归实现,求树高.我目前还是新手且第一次写类似的博客,文章中难免会有错误!如发现错误,望各路大神能够指出!详见源代码

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {

二叉树遍历递归与非递归实现

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 二叉树遍历是二叉树中非常基础的部分,也是学习二叉树必须熟练掌握的部分,下面我们先给出二叉树三种遍历方式的定义,并通过举例来说明二叉树遍历的过程. 二叉树的遍历分为:前序遍历(也叫先序遍历).中序遍历.后序遍历.所谓前.中.后都是根据当前子树根结点相对左右孩子的位置而言,也就是说: 前序遍历:根结点在前,即:根 ----->左------->右: 中序遍历:根结点在中间,即:左------>根------>右: 后序遍历:根结点在最

二叉树三种遍历(递归以及非递归实现)

package com.shiyeqiang.tree; import java.util.Stack; public class BiTree { public static void main(String[] args) { // 首先构造叶子节点 BiTree leafA1 = new BiTree(4); BiTree leafA2 = new BiTree(5); BiTree leafB1 = new BiTree(6); BiTree leafB2 = new BiTree(7)

二叉树遍历算法总结(递归与非递归)

一:前言 二叉树的遍历方法分四种:前序,中序,后序以及层次遍历. 其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈. 实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现. 而层次遍历需要借助队列. 二:前中后序遍历 递归遍历: 递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历. 代码如下: 1 void show(BiTree T) 2 { 3 if(T) 4 { 5 printf("%c ",T->data)

二叉树递归与非递归遍历,最近公共父节点算法

#include <iostream> #include <stack> using namespace std; #define MAX 100 //字符串最大长度 typedef struct Node //二叉树结点 { char data; Node *lchild,*rchild; } *Btree; void createBT(Btree &t); //先序构造二叉树 void preorder(Btree &t); //二叉树递归先序遍历 void i