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

  在前面先后介绍了二叉树先序遍历的非递归算法中序遍历的非递归算法,这里则来介绍二叉树后序遍历非递归算法,二叉树后序非递归遍历真的非常之

重要,因为它具有独特的特性(文章结尾会阐述),所以,在很多与二叉树相关的复杂算法中,经常要用到二叉树后序遍历的非递归算法。并且在互联网面试笔

试也经常考察该算法,所以,我们应该对二叉树后序遍历非递归算法乱熟于心。

  和二叉树先序遍历、中序遍历非递归算法一样,后序遍历非递归算法同样是使用栈来实现:从根结点开始,将所有最左结点全部压栈,每当一个结点出栈时,

都先扫描该结点的右子树,只有当一个结点的左孩子和右孩子结点均被访问过了,才能访问结点自身。

  二叉树后序遍历非递归算法实现如下:

  

#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 100
// 定义结点类型
typedef struct node
{
    int data;
    struct node* lchild;
    struct node* rchild;
} BTnode;

void Postorder(BTnode* t)
{
    BTnode* Seqstack[MAXSIZE];
    int top = -1;
    int falg = 1;
    BTnode* p;
    if(t != NULL)
    {
        do
        {
            while(t != NULL)                    // 循环,将所有最左结点压栈
            {
                top ++;
                Seqstack[top] = t;
                t = t->lchild;
            }
            flag = 1;                           // 辅助变量flag为1表示当前结点的左孩子为空或者已被访问
            p = NULL;                           // 指针变量p指向当前结点的前驱结点
            while(top > -1&& falg == 1)
            {
                t = Seqstack[top];              // 注意:这里只是获取栈顶元素,而并没有出栈
                if(t->rchild == p)              // 如果当前结点右孩子为空,或者已经被访问过,则访问当前结点
                {
                    top --;                     // 当前结点出栈
                    printf("%d ", p->data);
                    p = t;                      // 指针变量指向当前结点
                }
                else                            // 如果当前结点右孩子不为空,则先去处理右孩子
                {
                    t = t->rchild;              // 处理右孩子
                    flag = 0;                   // *t的左孩子未被访问,flag置为0
                }
            }
        }while(top > -1)
    }

}

  上面代码实现了二叉树后序遍历非递归算法(重点看懂注释),接下来就说一说前面提到的该算法的一个特性了:就是当访问某个结点时,栈中所保存的元素

正好是这个结点的所有祖先。那么知道了这个特性,我们就很容易解决下面如下问题:

(1).当给定一个叶子结点,要求输出该叶子结点的所有祖先

(2).输出根结点到所有叶子结点的路径

(3).如果二叉树结点的值是数值,那么求每条路径上值之和,也可以利用二叉树后序遍历的非递归算法这个特性

时间: 2024-12-24 19:11:17

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

二叉树遍历非递归算法——中序遍历

二叉树中序遍历的非递归算法同样可以使用栈来实现,从根结点开始,将根结点的最左结点全部压栈,当结点p不再有最左结点时,说明结点p没有左孩子,将该结点 出栈,访问结点p,然后对其右孩子做同样的处理. 二叉树中序遍历非递归算法实现如下: #include <stdlib.h> #include <stdio.h> #define MAXSIZE 100 // 定义结点类型 typedef struct node { int data; struct node* lchild; struc

【LeetCode-面试算法经典-Java实现】【145-Binary Tree Postorder Traversal(二叉树非递归后序遍历)】

[145-Binary Tree Postorder Traversal(二叉树非递归后序遍历)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, 1 2 / 3 return [3,2,1]. Note: Recursive soluti

非递归后序遍历二叉树(1)

1 void postOrder3(BinTree *root) //非递归后序遍历 2 { 3 stack<BinTree*> s; 4 BinTree *cur; //当前结点 5 BinTree *pre=NULL; //前一次访问的结点 6 s.push(root); 7 while(!s.empty()) 8 { 9 cur=s.top(); 10 if((cur->lchild==NULL&&cur->rchild==NULL)|| 11 (pre!=N

二叉树的前中后序遍历

#include<stdio.h> #include<string.h> #include<stdlib.h> #define Size 100 #define Resize 10 typedef struct Bitnode{ //定义结点 char data; struct Bitnode *lchild,*rchild; }Bitnode,*Bitree; typedef struct Stack{ //定义栈 Bitree *base; int top; int

栈实现二叉树的先,中,后序遍历

栈实现二叉树先,中,后序遍历 如果是使用递归来实现二叉树的先,中,后序遍历只需要更改三行代码的位置,但若是使用栈来写那便会有趣得多 根结点与其左右子树间的输出优先级 graph TD 1((根结点))---2((左子树)) 1---3((右子树)) 遍历方式 输出优先级 先序 根结点>左子树>右子树 中序 左子树>根结点>右子树 后序 左子树>右子树>根节点 使用栈的规则 栈内元素是指向结点的指针 只有栈顶元素指向的结点内容才会被输出 方便,不用记忆太多结点 结点内容输

七:重建二叉树(根据先序遍历(或者后序遍历)和中序遍历重建二叉树)

对于一颗二叉树,可以根据先序遍历(或者后序遍历)和中序遍历(树中不含重复的数字)重新还原出二叉树. 解析: 1. 先序遍历序列的第一个元素必定是根节点,可以由此获取二叉树的根节点. 2. 根据根节点,在中序遍历序列中查找该节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列必定在根节点的左子树中,而根节点右边的序列必定在右子树中.由此可以知道先序遍历中左子树以及右子树的起止位置. 3. 找到了左右子树前序遍历和中序遍历再用同样的方法分别构建左右子树,典型的递归思想. 代码如下: Binary

七:重建二叉树(依据先序遍历(或者后序遍历)和中序遍历重建二叉树)

对于一颗二叉树.能够依据先序遍历(或者后序遍历)和中序遍历(树中不含反复的数字)又一次还原出二叉树. 解析: 1. 先序遍历序列的第一个元素必然是根节点,能够由此获取二叉树的根节点. 2. 依据根节点,在中序遍历序列中查找该节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列必然在根节点的左子树中.而根节点右边的序列必然在右子树中.由此能够知道先序遍历中左子树以及右子树的起止位置. 3. 找到了左右子树前序遍历和中序遍历再用相同的方法分别构建左右子树,典型的递归思想. 代码例如以下: Bin

非递归 后序遍历二叉树

方法有很多,这里只举一种,先定义栈结点的数据结构typedef struct{Node * p; int rvisited;}SNode //Node 是二叉树的结点结构,rvisited==1代表p所指向的结点的右结点已被访问过. lastOrderTraverse(BiTree bt){ //首先,从根节点开始,往左下方走,一直走到头,将路径上的每一个结点入栈. p = bt; while(bt){ push(bt, 0); //push到栈中两个信息,一是结点指针,一是其右结点是否被访问过

二叉树(3)----后序遍历,递归和非递归方式

1.二叉树定义 typedef struct BTreeNodeElement_t_ { void *data; } BTreeNodeElement_t; typedef struct BTreeNode_t_ { BTreeNodeElement_t *m_pElemt; struct BTreeNode_t_ *m_pLeft; struct BTreeNode_t_ *m_pRight; } BTreeNode_t; 2.后序遍历 定义: 给定根节点,首先遍历左子树,然后遍历右子树,最后