二叉树(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、后序遍历

定义: 给定根节点,首先遍历左子树,然后遍历右子树,最后遍历根节点

(1)递归实现

如果根节点为空,则返回。

如果根节点不为空,则首先遍历左子树,然后遍历右子树,最后遍历根节点。

void  PostorderTraverse( BTreeNode_t *pRoot){
    if( pRoot == NULL ){
        return;
    }

    PostorderTraverse( pRoot->m_pLeft);
    PostorderTraverse( pRoot->m_pRight);
    Visit(pRoot);
}

(2)非递归方式

第一步:给定pRoot,判断pRoot是否为NULL;如果不为NULL,执行第二步;如果为NULL,执行第三步;

第二步:将pRoot入栈,并将pRoot的左结点赋给pRoot,执行第一步;

第三步:如果栈不为空,则将栈顶元素赋给pRoot,判断pRoot是否有右子树以及右子树是否访问过;如果没有右子树或者已经访问过右子树,则访问pRoot并出栈,然后执行第一步;如果有右子树并且右子树还没有访问过,则将pRoot右结点赋给pRoot,然后执行第一步。

void PostorderTraverse( BTreeNode_t *pRoot ){
    if( pRoot == NULL )
        return NULL;

    stack <BTreeNode_t *>  st;
    BTreeNode_t *visitedNode = NULL;
    while( pRoot != NULL || !st.empty() ){
        while( pRoot != NULL ){
            st.push( pRoot );
            pRoot = pRoot->m_pLeft;
        }

        if( !st.empty()){
            pRoot = st.top();
            if( pRoot->m_pRight == NULL || pRoot->m_pRight == visitedNode){
                Visited( pRoot);
                st.pop();
                pRoot = NULL;  //防止重复遍历,如果不赋值NULL,则会重复遍历
            } else {
                pRoot = pRoot->m_pRight;  //遍历右子树
            }
        }
    }
}

(3)非递归方式:使用双栈法

参考:http://blog.csdn.net/hackbuteer1/article/details/6583988

首先将根节点pRoot入栈1:

步骤一: 将栈1的栈顶元素赋给pRoot,然后将pRoot入栈2;然后先将pRoot左结点入栈1,后将pRoot右结点入栈1,顺序一定不能错。

步骤二:出栈2,就获得后序遍历

void  PostorderTraverse( BTreeNode_t *pRoot){
    if( pRoot == NULL )
        return;

    stack <BTreeNode_t *> st1;
    stack <BTreeNode_t *> st2;
    st1.push( pRoot);
    while( !st1.empty() ){
        pRoot = st1.top();
        st1.pop();
        st2.push( pRoot);
        if( pRoot->m_pLeft)
            st1.push( pRoot->m_pLeft);
        if( pRoot->m_pRight)
            st1.push( pRoot->m_pRight);
    }

    while( !st2.empty(){
        pRoot = st2.top();
        st2.pop();
        Visite( pRoot );
    }
    return;
}
时间: 2024-10-18 17:21:36

二叉树(3)----后序遍历,递归和非递归方式的相关文章

判断排序二叉树的后序遍历是否正确(对递归算的总结)

是 #include <iostream> using namespace std; //排序二叉树的性质 /* *.终止条件:1.开始>=结尾返回真 *. 2.s >= e 因为不出现问题的话,一定能到达 s>=e的情况.知道到达了s >= e即为真 *. 1.最后一个节点是root 2.在root之前的节点 连续的大于root的是其右子树, 再之前连续小于root的是其左子树 3.递归调用 */ bool treehelper(int a[], int s, int

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

思路: 二叉树的后序遍历非递归方法与前序,中序不同,稍微麻烦一些. 要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点cur,先将其入栈.如果cur不存在左孩子和右孩子,则可以直接访问它:或者cur存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点.若非上述两种情况,则将cur的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问. 代码如下: /** * Definition for

二叉树的后序遍历(非递归方法)

二叉树的后序遍历的话,利用stack进行非递归遍历,要先访问每个节点的左子树,在访问右子树,然后访问自身, stack 一直循环,当栈顶节点(cur)的左右子树都是None的时候, 或者当pre节点不是None的时候,同时pre和cur节点的左右子节点中的一个相等的时候 可以出栈并访问 # Definition for a binary tree node. # class TreeNode(object): # def __init__(self, x): # self.val = x # s

Binary Tree Postorder Traversal 二叉树的后序遍历

地址:https://oj.leetcode.com/problems/binary-tree-postorder-traversal/ 题意就是完成二叉树的后序遍历,我们知道如果使用递归进行二叉树后序遍历将是非常简单的事情. public class Solution { public List<Integer> postorderTraversal(TreeNode root) { List<Integer > ans = new ArrayList<>(); Tr

leetcode题解:Binary Tree Postorder Traversal (二叉树的后序遍历)

题目: 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 solution is trivial, could you do it iteratively? 说明: 1) 两种实现,递归与非递归 , 其中非递归有两种方法 2)复杂度分析:时

【leetcode 145. 二叉树的后序遍历】解题报告

前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> postorderTraversal(TreeNode* root) { if (!root) return res; if (root->left) postorderTraversal(root->left); if (root->right) postorderTraversal(root->right); res.push_back(ro

二叉树的后序遍历(暴力版) 小白菜oj 1034

给出二叉树的前序遍历和中序遍历,求二叉树的后序遍历-- 作为一个搜索蒟蒻,我真的没有办法很和谐的A掉,但估计过几天就会写有关这个题的和谐的解法--但只是估计-- 下面讲述我的超暴力解法-- 首先,先由前序遍历得到一个父亲节点,然后再由中序遍历得到这个父亲节点的左子树和右子树中的元素(中序遍历中,该点的左边的所有点,都在它的左子树,右边的都在它的右子树,子树中的根节点是在这些节点的前序遍历中排名最靠前的),然后递归建树,之后在递归求后序遍历即可. 但这个方法有两个比较--&¥--&的问题:1

[LeetCode] Binary Tree Postorder Traversal 二叉树的后序遍历

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 solution is trivial, could you do it iteratively? 经典题目,求二叉树的后序遍历的非递归方法,跟前序,中序,层序一样都需要用到栈,后续的顺序

判断序列是否是二叉树的后序遍历序列

这个题的意思就是给定一个序列,判断这个序列是否是某个二叉排序树的后序遍历序列,这个算法的方法主要是根据后序遍历的性质,首先这个序列的最后一个元素肯定是根元素,然后将序列从左往右遍历,找到第一个大于根元素的点,这个点左边的肯定是当前根的左子树,这个点的右边肯定是当前根的右子树,继续向后遍历,看右子树中是否有值小于根,如果有,则false,否则分左右子树分别再次调用函数进行判断.具体代码如下: 1 public class IsLastOrder{ 2 3 public boolean islast

已知二叉树的先序遍历序列和中序遍历序列,输出该二叉树的后序遍历序列

题目描述 输入二叉树的先序遍历序列和中序遍历序列,输出该二叉树的后序遍历序列. 输入 第一行输入二叉树的先序遍历序列: 第二行输入二叉树的中序遍历序列. 输出 输出该二叉树的后序遍历序列. 示例输入 ABDCEF BDAECF 示例输出 DBEFCA #include <iostream> #include <cstring> #define MAX 50+3 using namespace std; typedef char Elem_Type; typedef struct B