递归——递归数据结构相关问题解决—以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; }下面还有一种不太理想却有助于理解的思路
参考如下
1234567891011121314151617181920212223242526272829303132333435363738394041#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;
}
感悟:
对于递归结构体的题目,可以根据其定义将很多细节整体化,化繁为简。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!