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

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


(1)前序


    我们知道,前序遍历的顺序是根左右,当根节点不为空时,该节点才可以被打印。目前书上常见对树的遍历都是采用递归的方法实现的,我们知道递归必然会产生中断,也就是有现场信息的保存,如果要实现非递归,那么我们必须自己要有一个,用来保存现场信息

我先给出实现的伪代码,稍后我将解释为什么需要这么做,为何要用到这些条件。

伪代码如下:

1 void PreOrderTraverse(BinaryTree root)

2 {

3    BinaryTree cur = root;

4    stack<BinaryTree> s;

5    while(null != cur || !s.empty())

6    {

7        while(null != cur)

8        {

9            print cur.data;

10           s.push(cur);

11           cur = cur.left;

12       }

13       if(!s.empty()) {

14           cur = s.top();

15           s.pop();

16           cur = cur.right;

17       }

18   }     //loop end!

19}

第3行的cur就相当于递归中的现场信息,而第4行声明到的栈则用来保存它。

第5行的循环条件暂时不用关注,我们看第7行到第12行的代码,它主要做的是,如果当前节点不为空,则打印,同时将该结点的信息保存到用户栈中,接着把当前节点改变成它到的左子。当左子为空时,循环结束。

接着再看第13行到第16行的代码,它做的是取栈顶的现场信息(也就是最后一次保存的现场信息),然后改变当前结点为它的右子。

最后我们关注这个大循环结束的条件。当第16行执行结束,cur为右结点,可能存在两种情形:

① 右子为空,那么我们从用户栈恢复保存的现场信息。

② 右子不为空,那么整个逻辑不变,按照之前的方法进行处理。

所以我们得出整个循环继续得以执行的条件是结点不为空或者用户栈不空,满足二者其一即可。

(2)后序


    后序遍历的顺序是左右根,我们要保证根节点在左孩子和右孩子访问之后才能访问。

首先我们来考虑一个结点P能被访问的条件:

① P的左孩子和右孩子都为空,则该节点可以被直接访问;

② P有左孩子或右孩子,但左孩子和右孩子都已经被访问过,那么结点P也可以直接访问。

如果不是上面两种条件,那我们将P的右孩子和左孩子依次入栈,这样就可以保证每次取栈顶元素的时候,左孩子在右孩子的前面被访问,左孩子和右孩子都在根节点的前面被访问。

实现的伪代码如下:

void PostOrderTraverse(BinaryTree root)

{

if(null == root)

return;

stack<BinaryTree> s;

s.push(root);

BinaryTree pre = null;

BinaryTree cur;

while(!s.empty())

{

cur = s.top();

if(null == cur.lchild) && null == cur.rchild

|| (null != pre) && (pre == cur.lchild || pre == cur.rchild)) {

print cur.data;

s.pop();

pre = cur;

}

else {

if(null != cur.rchild) {

s.push(cur.rchild);

}

if(null != cur.lchild) {

s.push(cur.lchild);

}

}

}     //loop end!

}

时间: 2024-10-24 14:31:08

二叉树前序、后序和后序遍历(非递归实现)的相关文章

二叉树前序、中序、后序遍历非递归写法的透彻解析

前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历.递归写法,只要理解思想,几行代码.可是非递归写法却很不容易.这里特地总结下,透彻解析它们的非递归写法.其中,中序遍历的非递归写法最简单,后序遍历最难.我们的讨论基础是这样的: //Binary Tree Node typedef struct node { int data; struct node* lchild; //左孩子 struct node* rchild; //右孩子 }BTNode; 首先,有一点是明确的:非递归

前序中序后序遍历非递归实现

#include<iostream> #include<vector> #include<stack> #include<string> #include<algorithm> #include<numeric> using namespace std; class node{ public: int val; node* left; node* right; node():val(0),left(NULL),right(NULL){

二叉树的中序、先序、后序遍历非递归遍历算法(使用堆栈,用循环实现)

1 typedef struct TreeNode *BinTree; 2 typedef BinTree Position; 3 struct TreeNode{ 4 ElementType Data; 5 BinTree Left; 6 BinTree Right; 7 }; 8 BinTree BT; 9 void InOrderTraversal(BinTree BT)//中序遍历非递归遍历算法(使用堆栈,用循环实现) 10 { 11 BinTree T=BT; 12 Stack S=C

二叉树先序、中序、后续遍历非递归

1 ** 2 * 二叉树先序遍历非递归 3 * @param root 4 */ 5 public void preOrder_no_recursive(TreeNode root){ 6 if(root == null) return; 7 8 Stack<TreeNode> stack = new Stack<>(); 9 stack.add(root); 10 while(!stack.isEmpty()){ 11 TreeNode tn = stack.pop(); 12

二叉树前序遍历非递归写法

前序遍历非递归依靠栈实现,相对来说比较简单,先来用手写模拟一下基本就能知道怎么写了 据此可得如下代码 void preOrder_stack(BiTree T){ printf("\n非递归先序遍历结果:\n"); initStack(&sqStack); BiTree p=T; push(&sqStack,p); while(!stackEmpty(sqStack)){ pop(&sqStack,&p); printf("%d ",

二叉树的遍历(非递归)

1 //二叉树的先序遍历(非递归) 2 public void PreOrderTraverse() 3 { 4 BiTNode p = this.root; 5 Stack stack = new Stack(10000); 6 7 while(!stack.isEmpty || p != null) 8 if(p != null) 9 { 10 if(p.rchild != null) 11 stack.push(p.rchild); 12 System.out.print(p.data +

(编程训练)再回首,数据结构——二叉树的前序、中序、后序遍历(非递归)

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. 可以和(编程训练)再回首,数据结构--二叉树的前序.中序.后序遍历(递归)对比着看 [问题描述] 根据顺序存储结构建立二叉树的二叉链表,并对二叉树进行先序.中序.后序遍历. [基本要求] ·功能:根据顺序存储结构建立二叉树的二叉链表,并进行先序.中序.后序遍历. ·输入:输入二叉树的顺序存储. ·输出:二叉树的先序.中序.后序遍历序

二叉树的前序中序后序遍历-非递归-使用同一段代码实现

树的遍历通常使用递归,因为它的实现更简单,代码也更容易理解. 但在面试,或者特殊的情境中会使用到迭代算法(非递归). 此时需要使用栈去模拟函数栈调用过程. 本文将给出一段代码去实现这三种遍历 相比于传统的方式:前序遍历,中序遍历,后序遍历,使用不同的方式代码去实现,并且后续遍历更为难理解一些 可拓展性更好(比如N叉树的遍历),也更容易理解 考虑,对于一个函数栈,它除了存储了一些变量和指令,同时还存储了当前执行位置. 对于树的遍历,无非为:t->val,t->left ,t->right

二叉树中序遍历非递归写法

中序遍历比前序要稍微复杂些,我也先用手写理出思路 代码写的和书上的一比...感觉麻烦了好多,但毕竟是自己理的思路不容易忘,所以还是贴自己的 void inOrder_stack(BiTree T){ printf("\n非递归中序遍历结果:\n"); initStack(&sqStack); BiTree p=T,l;//l用于保存上次的输出 push(&sqStack,p); while(!stackEmpty(sqStack)){ getTop(&sqSta

leetcode144-先序遍历非递归实现

二叉树的先序/中序/后序遍历递归/非递归实现,讲的很清楚,其中后序遍历和先序中序的处理有些不一样: https://blog.yangx.site/2016/07/22/Python-binary-tree-traverse/ 原文地址:https://www.cnblogs.com/IcarusYu/p/10778236.html