poj2255 Tree Recovery 二叉树遍历

题目要求根据给定的二叉树前序遍历和中序遍历来求解后序遍历。前序遍历顺序为根-左-右,中序遍历顺序为左-根-右,后序遍历顺序为左-右-根。通过前序遍历可找到根节点,中序遍历可划分左右子树,递归遍历左右子树并最终输出根节点,从而得到后序遍历序列。
摘要由CSDN通过智能技术生成

题目链接:http://poj.org/problem?id=2255


题目大意:

      题目中给出一个二叉树的前序遍历和中序遍历,输出这个二叉树的后序遍历。二叉树中的点是大写英文字母,最多有26点。

 

解题思路:

    这道题涉及到一种重要的数据结构——二叉树,题目很简单,但是考查了对二叉树的遍历的理解。二叉树,顾名思义,就是每一个点都有两个子点的树。二叉树的遍历主要有四种:前序遍历、中序遍历、后序遍历和层序遍历。前三种都是使用栈来实现遍历,只是访问点的顺序不同(有点像深搜),而层序遍历是使用队列来实现遍历(有点像广搜)。

前序遍历:先访问根结点,再遍历左子树,后遍历右子树;

中序遍历:先遍历左子树,再访问根结点,后遍历右子树;

后序遍历:先遍历左子树,在遍历右子树,后访问根结点。

例如:

     二叉树:

             

    

前序遍历:ABDECFG

在前序遍历中,先访问结点,然后访问左子树上遇到的每一个结点,继续这个过程,直到一个结点的左结点是空节点。这时,返回到最近的有右子树的父亲结点,并从该结点的右子树继续遍历。代码:


void preorder(tree_pointer ptr)
{
    if (ptr) {
        printf("%d",ptr -> data);
        preorder(ptr -> left_child);
        preorder(ptr -> right_child);
    }
}


中序遍历:DBEAFCG

中序遍历就是从二叉树的根结点开始,向树的左子树移动,直到遇到空结点为止,然后访问空结点的父亲结点,接着继续遍历这个结点的右子树。如果右子树没有子结点可以遍历,那么就继续遍历上一层最后一个未被访问的结点。代码:

 

void preorder(tree_pointer ptr)
{
    if (ptr) {
        preorder(ptr -> left_child);
        printf("%d",ptr -> data);
        preorder(ptr -> right_child);
    }
}

后序遍历:DEBFGCA

在后序遍历中,先遍历结点的左右子树,然后才对该结点进行访问。代码:

    

void postorder(tree_pointer ptr)
{
    if (ptr) {
        postorder(ptr -> left_child);
        postorder(ptr -> right_child);
        printf("%d",ptr -> data);
    }
}

在这道题中,题目给出了二叉树的前序遍历和中序遍历。从前序遍历我们可以知道根结点,从中序遍历我们可以知道某个结点的左右子树。所以先递归左子树,再递归右子树,最后输出根结点。这个顺序就是后序遍历的顺序。

例如:图中的二叉树,中序遍历是:DBEAFCG,前序遍历是:ABDECFG。由前序遍历我们可以知道二叉树的根结点是A。所以在中序遍历中:可以得到DBEA结点的左子树,FCGA结点的右子树。所以继续遍历左子树,即:。这时,由前序遍历我们可以知道B是子树DBE的根结点,所以继续遍历左子树,即:。此时,D结点既没有左子树,也没有右子树,将D结点输出。不断继续这个过程,直到输出所有结点。

代码:

/*
     ID: Code-Cola
     PROG: 2255
     LANG: C++
*/

#include<iostream>
#include<cstdio>
#include<string>

using namespace std;

/********** 全局变量 **********/

string s_preorder, s_inorder;                                           //字符串类存储前序遍历和中序遍历

/********** 函数声明 **********/

void postorder(int first, int last, int root);                          //递归遍历

int main()
{
    int i;
    while (cin >> s_preorder >> s_inorder) {
        postorder(0,s_inorder.size() - 1, 0);                           //从字符串的左右位置开始遍历
        cout << endl;
    }
    return 0;
}

void postorder(int first, int last, int root)
{
    if (first <= last) {
        postorder(first, s_inorder.find(s_preorder[root]) - 1, root + 1);//遍历左子树 注意左右位置
        postorder(s_inorder.find(s_preorder[root]) + 1, last, root + 1); //遍历右子树
        cout << s_preorder[root];                                        //输出结点
        s_preorder.erase(root,1);                                        //删除已输出的结点
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值