poj2255 Tree Recovery 二叉树遍历

时间:2021-12-30 17:29:49

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


题目大意:

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

 

解题思路:

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

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

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

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

例如:

     二叉树:

             poj2255 Tree Recovery 二叉树遍历

    

前序遍历: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。所以在中序遍历中:poj2255 Tree Recovery 二叉树遍历可以得到DBEA结点的左子树,FCGA结点的右子树。所以继续遍历左子树,即:poj2255 Tree Recovery 二叉树遍历。这时,由前序遍历我们可以知道B是子树DBE的根结点,所以继续遍历左子树,即:poj2255 Tree Recovery 二叉树遍历。此时,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); //删除已输出的结点
}
}