递归——递归数据结构相关问题解决—以American Heritage问题为例

问题描述:

Farmer John takes the heritage of his cows very seriously. He is not, however, a truly fine bookkeeper. He keeps his cow genealogies as binary trees and, instead of writing them in graphic form, he records them in the more linear tree in-order" and tree pre-order" notations.

Your job is to create the `tree post-order" notation of a cow"s heritage after being given the in-order and pre-order notations. Each cow name is encoded as a unique letter. (You may already know that you can frequently reconstruct a tree from any two of the ordered traversals.) Obviously, the trees will have no more than 26 nodes.

Here is a graphical representation of the tree used in the sample input and output:

              C
            /   
           /     
          B       G
         /      /
        A   D   H
           / 
          E   F

The in-order traversal of this tree prints the left sub-tree, the root, and the right sub-tree.

The pre-order traversal of this tree prints the root, the left sub-tree, and the right sub-tree.

The post-order traversal of this tree print the left sub-tree, the right sub-tree, and the root.

--------------------------------------------------------------------------------

题目大意:

给出一棵二叉树的前序遍历 (preorder) 和中序遍历 (inorder),求它的后序遍历 (postorder)。

你需要知道的:

1:二叉树的 相关定义可以在书上或者网上找到。

2:样例 输入输出反映的二叉树在上面。

输入描述

Line 1:

The in-order representation of a tree.

Line 2:

The pre-order representation of that same tree.

输出描述

A single line with the post-order representation of the tree.

样例输入

ABEDFCHG

CBADEFGH

样例输出

AEFDBHGC

 

解题思路:

这是一个关于递归数据结构的算法题。具体来说是个二叉树,无论多大的二叉树都可以看成是一个根结点和左右孩子的结合。

所以只要关注三个点就够了。

根据前序遍历的序列我们可以知道第一个元素为树的根结点,再更具中序遍历的序列,可以由已知的根结点来找到左右孩子。如果左右孩子也可看做是树(即不为空),那么继续重复以上过程。

对三个结点的树来说,根节点是最后输出,所以应该采用头递归,将输出结点的步骤放在最后。

 

源码如下:

复制代码
#include<stdio.h>
#include<string.h>
void hoge(char *pre,char *in,int length){
    char c=pre[0];
    if(length == 0){
        return;
    }
    if(length ==1){
        printf("%c",c);
        return;
    }
    int i=0;
    while(in[i]!=c){
        i++;
    }
    hoge(pre+1,in,i);
    hoge(pre+i+1,in+i+1,length-1-i);
    printf("%c",c);
}
int main(){
    char pre[30],in[30];
    int length;
    while(scanf("%s%s",pre,in)!=EOF){
        length = strlen(pre);
        hoge(in,pre,length);
    }
    return 0;
}
复制代码

下面还有一种不太理想却有助于理解的思路

参考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedef struct BTNode{
    char data;
    struct BTNode *lchild;
    struct BTNode *rchild;
}BTNode; //创建二叉树结点
 
BTNode *CreateBTree(char a[],char b[],int n){
    int k;
    if(n<=0) return NULL; //递归出口:没有剩余结点时,返回空结点
    char root = a[0] ;
    BTNode *bt = (BTNode*)malloc(sizeof(BTNode)); //创建每个分结点的根结点
    bt->data = root;
    for(k=0;k<n;k++)
        if(b[k] == root)
            break;
    bt->lchild = CreateBTree(a+1,b,k);
    bt->rchild = CreateBTree(a+k+1,b+k+1,n-k-1);//递归体:确定了根节点,连接左右结点
    return bt;
} //时间复杂度为log(N)
 
void LRD(BTNode *bt){
    if(bt == NULL) return;//递归出口:遇到空结点时则弹出栈
    LRD(bt->lchild);//递归体:对一棵树先完成输出左孩子再完成输出右孩子最后输出自己
    LRD(bt->rchild);
    printf("%c",bt->data);
}//时间复杂度为N
 
int main(){
    char a[10000] = "";
    char b[10000] = "";
    while(scanf("%s%s",a,b)!=EOF){
        int length = strlen(a);
        BTNode *bt = (BTNode*)malloc(sizeof(BTNode));
        bt=CreateBTree(b,a,length);
        LRD(bt);
    }
    return 0;
}

 感悟:

对于递归结构体的题目,可以根据其定义将很多细节整体化,化繁为简。

posted @   chanxe  阅读(94)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!
点击右上角即可分享
微信分享提示