二叉树的一个算法 大家探讨一下思路并用程序实现

softwarewander 2006-11-03 05:11:33
条件:已知某个二叉树的后续遍历结果 和中序遍历结果
目的:构建出一个二叉树,并以先序的顺序打印出来节点的值

要求:需要最少的空间和时间复杂度


例如:后序遍历结果 “DEBHCA”
中序遍历结果 “DBEACH”

输出应该是:ABDECH













...全文
1144 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
jojophak 2006-11-06
  • 打赏
  • 举报
回复
mark
jinweichao 2006-11-05
  • 打赏
  • 举报
回复
好思路,但感觉好像是书上的
zhanglin03130410 2006-11-05
  • 打赏
  • 举报
回复
tong
gaiguzi_youmin 2006-11-05
  • 打赏
  • 举报
回复
诸位可不可以再用类写一个实现二叉树历遍的算法啊,这样的算法我看着觉得有点乱啊————
softwarewander 2006-11-04
  • 打赏
  • 举报
回复
赫赫,这里的递归实现的主要过程是抄袭了 pcboyxhy 的

我原来在递归的实现过程中想到的是这样的:
1。现在后序遍历序列中找到最后一个作为整棵树的根节点。比如是 ‘A’
2。在中序遍历表中找到根节点的位置。 其左侧的是根节点的左子树。(D,B,E)然后再回到后续表中找这些节点中的最后一个节点 (B)因此B是根节点的左孩子;
其右侧的是根节点的右子树(C,H)这些节点在后续表中最后一个是 (C)因此C是根节点的右孩子
3。循环2的过程 即可完成递归

但是我在找后序遍历表中那些节点的最后一个的时候,还有确定中序遍历表中那些已经做过处理等 想作标记 但是不知道什么时候做不太好处理

pcboyxhy 的实现思路从后面往前推,位置号<0为递归出口 很巧妙阿!
softwarewander 2006-11-04
  • 打赏
  • 举报
回复
#include <string.h>
#include <stdio.h>


#define MAX 20

typedef struct node
{
char data;
struct node *lchild,*rchild;
}BiNode;


//int top=-1;

typedef BiNode * BiTree;

//char stack[MAX];

//#define push(s) stack[++top]=s
//#define pop stack[top--]

char a[] = "DEBHCA" ;
char b[] = "DBEACH" ;


void print(BiTree t)
{
if(t)
{
printf("%c",t->data);
print(t->lchild);
print(t->rchild);
}
}


BiTree create(char *b, char *a, int rootpos)
{
BiNode * ptr=(BiNode *)malloc(sizeof(BiNode));
char ch, l=rootpos;
if(rootpos<=0)
{
return (BiNode *)0;
}
ch = a[rootpos-1]; //后序遍历最后一个访问的是根
ptr->data =ch; //记录该节点的值信息
ptr->lchild=(BiNode *)0;
ptr->rchild=(BiNode *)0;

while(l--){
if(b[l]==ch)
{ //中序遍历的结果中,根左边的都是左子树,根右边的都是右子树
ptr->lchild =create(b, a, l); //递归处理根左边的子树:@1
ptr->rchild=create(b+l+1, a+l, len-l-1); //递归处理根节点右边的子树 @2
return ptr; //返回整个的根节点
}
}
}


int _tmain(int argc, _TCHAR* argv[])
{
BiTree proot;
proot=create(b,a,strlen(a));
print(proot);
printf("\n");
system("pause");

return 0;
}
lgsh_007 2006-11-04
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void exit(int);
#define max 100
typedef struct node
{
char d;
struct node *lchild,*rchild;
}tnode;

void mktree(char in[],int is,int ie,char post[],int posts,int poste,tnode **r)
{
int i;
if(is>ie||posts>poste)
{
*r=NULL;
}
else
{
*r=malloc(sizeof(tnode));
(*r)->d=post[poste];
for(i=0;i<=ie;i++)
if(post[poste]==in[i])
{
mktree(in,is,i-1,post,posts,posts+i-is-1,&(*r)->lchild);
mktree(in,i+1,ie,post,posts+i-is,poste-1,&(*r)->rchild);
break;
}
if(i>ie)
{
printf("error: input contains an error1\n");
exit(1);
}


}
}

void preorder(tnode *r)
{
if(r)
{
printf("%c",r->d);
preorder(r->lchild);
preorder(r->rchild);
}

}

void main()
{
tnode *r;
char in[max],post[max];
printf("input inorder and postorder!\n");
gets(in);
gets(post);
mktree(in,0,strlen(in)-1,post,0,strlen(post)-1,&r);
printf("the preorder is as follows:\n");
preorder(r);

}

结分吧!经测试了,大概思路,1,把前序串放到in[],后序串放到post[],根就是post的最后一个字符,再在in中找到和post最后字符相等的字符,这时就分开了左右子树,之后递归
jakiejia 2006-11-04
  • 打赏
  • 举报
回复
softwarewander () 此人发的二叉树中序错误!!!
应该是


中序:DBEAHC

A

B C

D E H
此为二叉树!!!
代码就不用写了吧????QQ:562033873
hedongfu 2006-11-04
  • 打赏
  • 举报
回复
一个类似的例子,你看看吧
二叉查找树(binary search tree (BST))--算法导论示例

http://blog.csdn.net/hedongfu/archive/2006/09/12/1211007.aspx
BCB 2006-11-04
  • 打赏
  • 举报
回复
当初学数据结构时,是书后的练习题,
大家几乎没有困难,象softwarewander()的思路
yuyang5212 2006-11-04
  • 打赏
  • 举报
回复
是个数据结构的教科书就有,好好看看书吧
softwarewander 2006-11-03
  • 打赏
  • 举报
回复
呵呵 有点事才回来 想不到这么多回复阿
首先声明, 这个题目不是我从哪里看到的, 完全是自己想的, 那些软件水平考试 本人觉得没什么用, 证书并不一定代表实力。 如有雷同,纯属巧合哈 :)

jixingzhong(瞌睡虫·星辰):
你没有看清楚我的条件阿 你的方法是由先序,和中序遍历序列得出二叉树。



pcboyxhy兄的主要思路和我一样, 但这种递归调用的形式我没想到。但是只是按照先序顺序输出了, 并没有指明谁是谁的左孩子或是右孩子啊, 我的意思是还没有构建出他们之间的关系, 然后调用标准的先序递归算法输出。


今天 不早了 ,先睡了, 明天我把代码整理一下,看看还有没有改进的地方。
pcboyxhy 2006-11-03
  • 打赏
  • 举报
回复
稍微整理一下

#include <stdio.h>
#include <string.h>

void make(char *mid, char *lst, int len)
{
char ch, l=len;
if(len<=0) return; //数为空
ch = lst[len-1]; //后序遍历最后一个访问的是根
putchar(ch); //输出这个根
while(l--){
if(mid[l]==ch){ //中序遍历的结果中,根左边的都是左子树,根右边的都是右子树
make(mid, lst, l); //递归处理根左边的结点
make(mid+l+1, lst+l, len-l-1); //处理右边的
return;
}
}
}

int main( )
{
char midrt[100], lstrt[100];
gets(midrt);
gets(lstrt);
make(midrt, lstrt, strlen(midrt));
putchar('\n');
}
jixingzhong 2006-11-03
  • 打赏
  • 举报
回复
软件设计师 考试题目 ...
jixingzhong 2006-11-03
  • 打赏
  • 举报
回复
问题1:关于二叉树的排序,有这样一个程序:

由二叉树的前序遍历和中序遍历两个遍历序列能唯一确定一棵二叉树.

如前序遍历:A,B,D,E,C,F,G; 中序遍历:D,B,E,A,,C,G,F;如以下事例;

A

B C

D E F

G

本程序实现已知某二叉树的前序遍历和中序遍历序列,生成一棵连接表示的二叉树.

构造二叉树的算法要点是:由前序遍历序列,该序列的第一元素是根接点元素(例中A).该元素将中序遍历序列分成左右两部分,那些位于该元素之前的元素是它的左子树上的元素(如D,B,E);位于该元素之后的元素是它右子树上的元素(如C,G,F);对于左右子树,由他们的前序遍历序列的第一个元素可确定左,右子树的根接点,参照中序遍历序列又可进一步确定子树的左右子树元素.如此递归参照两个遍历序列,最终构造出二叉树

两个遍历序列作为主函数main()的参数.为简单起见,程序假定两个遍历序列是相容的.主函数调用函数restore()建立的二叉树.函数restore()以树(子树)的前序遍历和中序遍历两序列及序列长为参数,采用递归方法建立树(子树).

函数postorder()实现二叉树的后续遍历输出,用来验证函数restore()建立的二叉树.

#include <stadio.h>

#include<stdlib.h>

#define MAX 100

typedef struct node{

char info;

struct node *llink,*rlink;

}TNODE;

char pred[MAX],inod[MAX];

TNODE restore(char*,char *,int);

Main(int argc,char **argv)

{ TNODE *root;

if(argc<3)exit(0);

strcpy(pred,argv[1]);

strcpy(inod,argv[2]);

root=restore(pred,inod,strlen(pred));

postorder(root);

printf(“\n\n”);

}

TNODE*restore(char*ppos,char*ipos,int n)

// char*ppos为前序列,char*ipos为中序列 ,n为长度

{ TNODE *pre;

char *rpos;

int k;

if(n<=0) return Null;

ptr=(TNDOE *)malloc(sizeof(TNDOE));

ptr->info=ppos .info; 1 //确定根节点

for(rpos=ipos;rpos<ipos+n;rpos++) 2

if(*rpos==*ppos)break;

k=ipos+n-rpos; 3

ptr->llink=restore(ppos+1,ipos,k); 4

ptr->rlink=testore(ppos+k, 5

rpos+1,

n-1-k);

return ptr;

}

postorder(TNDOE *ptr)

{ if (ptr==NULL) return;

postorder(ptràllink);

postorder(ptràrlink);

printf(“%c”,ptràinfo);

}

解答:

首先我先说明我的答案是我自己根据题目给出的信息得出的答案,如果你有标准答案可以给我发过来,大家一起研究

看这个题目,主要就是两个序列,说明给的很清楚根据前序的节点划分中序的序列;

比如第一个空,我觉得是先确定根节点也就是前序的第一个点;

然后,遍历中序序列寻找前序的节点,如果找到,那么就递归调用左子树和右子树继续寻找;当然递归调用的参数还是两个序列和序列的长度;

ptr->llink=restore(ppos+1,ipos,k);//左子树,首先前序的根节点已经求出,那么前序序列就从ppos+1开始,中序仍然从ipos开始,,但是长度变化了,变为根节点前的部分序列的长度,因为这个部分才识左子树部分

同样的道理:ptr->rlink=testore(ppos+k, rpos+1, n-1-k)//前序序列从去掉左子树和根节点开始,中序序列就从找到跟节点的后一个位置开始,长度就是n-(k+1),这样递归就完成了;

针对这样的问题主要要理解题目之前的说明,这些说明是你解答的思路;

iambic 2006-11-03
  • 打赏
  • 举报
回复
A
/ \
B C
/ \ \
D E H

不对吗?
SammyLan 2006-11-03
  • 打赏
  • 举报
回复
看错了...
SammyLan 2006-11-03
  • 打赏
  • 举报
回复
又是迅雷的笔试题(=_=)
pcboyxhy 2006-11-03
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <string.h>

void make(char *pmid, char *qmid, char *plst, char *qlst)
{
char ch, *rt=pmid;
if(pmid==qmid) return;
ch = *(qlst-1);
putchar(ch);
while(rt<qmid){
if(*rt==ch){
make(pmid, rt, plst, plst+(rt-pmid));
make(rt+1, qmid, plst+(rt-pmid)+1, qlst-1);
return;
}
rt++;
}
}

int main( )
{
char midrt[100], lstrt[100];
gets(midrt);
gets(lstrt);
make(midrt, midrt+strlen(midrt), lstrt, lstrt+strlen(lstrt) );
putchar('\n');
}

没有创建树
laiwusheng 2006-11-03
  • 打赏
  • 举报
回复
例子有问题,完毕!
加载更多回复(4)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧