二叉树--后序遍历的非递归算法

后续遍历关键在于,当节点的  右子树存在且被访问后  或者是  右子树为空  才能访问自身。

在遍历过程中,先将节点从的左孩子到最左节点压栈, 设置标志变量 flag 来判断是否访问过左孩子, pre指针来指向先前访问过的节点。

所有左孩子压栈后, 最后一个节点的左孩子为空,已被访问p = NULL , 令flag=1

当左孩子被访问时,进入循环,取栈顶节点。

1. 当栈顶节点的右孩子 等于 空  或  前一个被访问的节点  时, 访问该节点, 令pre 等于当前节点,pre = p, 当前节点出栈。

2. 当栈顶节点的右孩子不为空时, 继续遍历以右孩子为根节点的右子树。

 1 Status PostOrderTraverse(BiTree T){
 2     BiTree p = T, S[100], pre;
 3     int top = 0, flag = 1;
 4     if(p)
 5         do{
 6             while(p){
 7                 S[top++] = p;
 8                 p = p->lchild;
 9             }
10             // p所有左节点入栈
11             flag = 1;
12
13             while(top != 0 && flag == 1){
14                 p = S[top-1];
15                 if(p->rchild == pre || p->rchild == NULL){
16                 //右孩子不存在或右孩子已访问
17                     top--;
18                     printf("%c ", p->data);
19                     pre = p;
20                     //指向被访问节点
21                 }
22                 else{
23                     //继续遍历右子树
24                     p = p->rchild;
25                     flag = 0;
26                 }
27             }
28         }while(top != 0);
29     return OK;
30 }//PostOrderTraverse       

完整代码:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3
 4 #define TElemType char
 5 #define Status int
 6 #define OK 1
 7
 8 typedef struct BiTNode{
 9     TElemType data;
10     struct BiTNode *lchild, *rchild;
11 }BiTNode, *BiTree;
12
13 Status CreateBiTree(BiTree &T){
14     TElemType ch = getchar();
15     if(ch == ‘#‘) T = NULL;
16     else{
17         T = (BiTree)malloc(sizeof(BiTNode));
18         T->data = ch;
19         CreateBiTree(T->lchild);
20         CreateBiTree(T->rchild);
21     }
22     return OK;
23 }//CreateBiTree
24
25 Status PostOrderTraverse(BiTree T){
26     BiTree p = T, S[100], pre=NULL;
27     int top = 0, flag = 1;
28     if(p)
29         do{
30             while(p){
31                 S[top++] = p;
32                 p = p->lchild;
33             }
34
35             flag = 1;
36
37             while(top != 0 && flag == 1){
38                 p = S[top-1];
39                 if(p->rchild == pre || p->rchild == NULL){
40                     top--;
41                     printf("%c ", p->data);
42                     pre = p;
43                 }
44                 else{
45                     p = p->rchild;
46                     flag = 0;
47                 }
48             }
49         }while(top != 0);
50     return OK;
51 }//PostOrderTraverse
52
53 int main(){
54     BiTree T;
55     CreateBiTree(T);
56     PostOrderTraverse(T);
57     return 0;
58 }

原文地址:https://www.cnblogs.com/Dawn-bin/p/9844442.html

时间: 2024-10-01 04:35:40

二叉树--后序遍历的非递归算法的相关文章

二叉树后序遍历的非递归算法(C语言)

首先非常感谢‘hicjiajia’的博文:二叉树后序遍历(非递归) 这篇随笔开启我的博客进程,成为万千程序员中的一员,坚持走到更远! 折磨了我一下午的后序遍历中午得到解决,关键在于标记右子树是否被访问过,考虑过修改二叉树结点的数据结构,增加一个visit域,或者建一个栈存储已访问的结点.都比较麻烦没有调试成功.若将右子树也入栈,如果没有访问标记的话,会改变访问的次序,甚至出现死循环,这是比较危险的情况.从借鉴的博文里,摘录并改写为C的代码,基本上没有改动.后续问题努力写出自己的原创代码. 二叉树

二叉树的前序建立,前中后序遍历的非递归算法

二叉树的前序建立递归算法以及前中后序遍历的递归算法已经是人尽皆知了,递归算法也确实为代码的编写带来了很大的方便.然而,有时我们也确实需要它们的非递归算法.将递归算法转化为非递归算法可以帮助我们深入了解函数的调用与栈的原理.这里总结一下二叉树的这些重要的非递归算法. 一.前序建树 前序建树的基本思路是,接收用户输入的一组字符串,其中'#'代表空树,其他代表树结点的数据域值.例如,要建立如下一棵树 需要输入"AB#D##C##". 而非递归的思路是,1.设一个标志位来判断当前创建的结点是左

DS二叉树--后序遍历非递归算法

题目描述 求一颗树的后序遍历的非递归算法 要求:必须是非递归算法,使用堆栈对象来实现 建树方法采用“先序遍历+空树用0表示”的方法 算法流程: 输入 第一行输入一个整数t,表示有t个测试数据 第二行起输入二叉树先序遍历的结果,空树用字符‘0’表示,输入t行 输出 逐行输出每个二叉树的后序遍历结果 样例输入 3 AB0C00D00 ABC00D00EF000 ABCD0000E0F00 样例输出 CBDA CDBFEA DCBFEA 提示 #include<iostream> #include&

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

1 二叉树的前序遍历 对于每棵子树,先处理根,然后处理左子树,最后处理右子树.根最先访问,所以是前序遍历. 2 二叉树的中序遍历 对于每棵子树,先处理左子树,然后处理根,最后处理右子树.根中间访问,所以是中序遍历. 3 二叉树的后序遍历 对于每棵子树,先处理左子树,然后处理右子树,最后处理根.根最后访问,所以是后序遍历. 4 二叉树后序遍历的非递归实现 如果pre为NULL: 左右儿子都是NULL,那么自己出栈: 如果左儿子为NULL,右儿子不为NULL,右儿子进栈: 如果左儿子不为NULL,那

二叉树高度,以及栈实现二叉树的先序,中序,后序遍历的非递归操作

求解二叉树的高度 树是递归定义的,所以用递归算法去求一棵二叉树的高度很方便. #include <iostream> #include <cstdio> using namespace std; struct Node { char data; Node *lchild; Node *rchild; }; void High(Node *T, int &h) { if (T == NULL) h = 0; else { int left_h; High(T->lchi

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

二叉树前序.后序和后序遍历(非递归实现) (1)前序     我们知道,前序遍历的顺序是根左右,当根节点不为空时,该节点才可以被打印.目前书上常见对树的遍历都是采用递归的方法实现的,我们知道递归必然会产生中断,也就是有现场信息的保存,如果要实现非递归,那么我们必须自己要有一个栈,用来保存现场信息. 我先给出实现的伪代码,稍后我将解释为什么需要这么做,为何要用到这些条件. 伪代码如下: 1 void PreOrderTraverse(BinaryTree root) 2 { 3    Binary

二叉树基本操作续二:前序、中序、后序遍历(非递归 迭代方式)

这里给出二叉树三种遍历方式的迭代实现代码.二叉树的递归实现使用系统栈入栈出栈,而非递归的迭代实现方法就是手动维护一个栈,来模拟递归的入栈出栈过程. 本文没有给出用户栈的代码,如果需要结合上篇的测试代码一起测试,则需要自己实现自己的栈,以及基本的pop.push等栈操作函数. 前序迭代遍历: 1 void iter_preorder(tree_pointer ptr) 2 { 3 //前序遍历:先遍历根节点,然后再分别遍历左右子树 4 int top = -1; 5 tree_pointer st

二叉树非递归先中后序遍历 及 非递归交换二叉树两个孩子的位置

看到一个非递归交换一个二叉树的左右孩子的位置,于是想实现之,才发现非递归的先中后序遍历都忘记了……于是杂七杂八的写了一些,抄抄资料就实现了,然后实现非递归交换两个孩子的位置还是相当容易的.先直接上代码吧,其实这东西还是得自己写写过一遍的,印象才会更加深刻: #include <iostream> #include <fstream> #include <string> #include <stack> using std::cout; using std::

数据结构之 二叉树---求二叉树后序遍历和层次遍历(先建树,再遍历)

数据结构实验之求二叉树后序遍历和层次遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 已知一棵二叉树的前序遍历和中序遍历,求二叉树的后序遍历. 输入 输入数据有多组,第一行是一个整数t (t<1000),代表有t组测试数据.每组包括两个长度小于50 的字符串,第一个字符串表示二叉树的先序遍历序列,第二个字符串表示二叉树的中序遍历序列. 输出 每组第一行输出二叉树的后序遍历序列,第二行输出二叉树的层次遍历序列 示例输入 2 abdegcf dbgeaf