二叉树的问题。。

j8daxue 2010-10-11 05:36:25
描述

对于一棵二叉树,有三种遍历。

如果给出前序遍历和中序遍历,那么后序遍历是唯一确定的。

但是如果只知道前序遍历和后序遍历,那么中序遍历是不确定的。

例如前序遍历是ABCD,后序遍历是CBDA,那么中序遍历可以是 CBAD 或者 BCAD

现在的问题是给出前序遍历和后序遍历,要求出中序遍历有多少种不同的方案。


输入

输入有两行,第一行是前序遍历,第二行是后序遍历,结点用大写字母表示

输出

输出一行,为方案总数

样例输入

ABCD
CBDA


样例输出

2

思路:
中序之所以不确定,是因为面对着
根左右(先)
左右根(后)
找到这个根后,左边的节点是左还是右的抉择
如ABCD,CBDA.
找到根A后
查看BCD CBD。则B为左子树的根, D为右子树的跟。
对于BC(根左右),CB(左右根)C可以是B的左或者右子树,所以结果*2.

代码:

int mid_visit(string pre,string after)
{
int cnt = 1;
//根据前序结果找根
char ch_root = pre[0];
//后序结果中根的位置
int pos_root = after.find(ch_root);
//左右子树长度
int len_left = pos_root;
//右子树长度
int len_right = after.length() - pos_root - 1;
if(len_right)
{
string sub_pre = pre.substr(1 + len_left,len_right);
string sub_after = after.substr(1 + len_left,len_right);
//右子树长度为1,只有一个节点,一种情况
if(len_right == 1)
cnt *= 1;
//递归右子树
else
cnt *= mid_visit(sub_pre,sub_after);
}
if(len_left)
{
string sub_pre = pre.substr(1,len_left);
string sub_after = after.substr(0,len_left);
//左子树长度为1,面对类似上面的选择
if(len_left == 1)
cnt *= 2;
else
cnt *= mid_visit(sub_pre,sub_after);
}
return cnt;
}

但结果不对。
如ABCDE,CBDEA,这个结果该是什么?
是思路不对还是代码里呢?
...全文
351 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
somebody 2010-10-15
  • 打赏
  • 举报
回复
还可以这样试试:把后序排列倒过来。利用先序可以确定最靠左的叶节点!可以划分出根节点的左右孩子序列!
如ABCDE,CBDEA
A是根节点,c是最靠左的叶节点
后序倒过来就是:AEDBC.于是乎就可以确定bc,de分别是以A为根节点的左、右子树!一次类推……
somebody 2010-10-15
  • 打赏
  • 举报
回复
查看BCD CBD。则B为左子树的根, D为右子树的跟。
对于BC(根左右),CB(左右根)C可以是B的左或者右子树,所以结果*2.

提醒:树是有这么多种形态,但是遍历输出可能不具有这么多形态!其中存在不完全二叉树和完全二叉树!如果是不完全二叉树,就可能会少于*2种结果。完全二叉树才有那么多种结果!
你的程序问题就出在这儿吧!

不单单有先序的头和后序的尾来判断它的根节点。
还应该利用后序的头就是整颗树的最左边叶节点。而先序的尾就是根节点下一层节点!
如ABCDE,CBDEA
A是根节点,c是最靠左的叶节点!
hhboring 2010-10-15
  • 打赏
  • 举报
回复
我是P的 自己凑活看吧

var
sa, sb: Ansistring;
procedure Main;
var
i: longint;
m: longint;
begin
readln(sa);
readln(sb); sb := sb + '@';
m := 0;
for i := 2 to length(sa) do
if (sa[i - 1] = sb[pos(sa[i], sb) + 1]) then inc(m);
writeln(1 shl m);
end;
begin
Main;
end.
j8daxue 2010-10-12
  • 打赏
  • 举报
回复
help!
知道很多人鄙视求作业题答案。
但这个真的不是作业题。
Corepy 2010-10-11
  • 打赏
  • 举报
回复

二叉树的建立,先序,中序,后序非递归遍历

#include<stdio.h>
#include <iostream>
using namespace std;

//二叉树链式存储的头文件
typedef char datatype; //结点属性值类型
typedef struct node //二叉树结点的类型
{
datatype data;
struct node* lchild,*rchild;
}bintnode;
typedef bintnode *bintree;
bintree root; //指向二叉树根结点指针

//下面是些栈的操作 为非递归实现做准备

typedef struct stack //栈结构定义
{
bintree data[100]; //data 元素类型为 指针
int tag[100]; //为栈中元素作的标记,用于后序遍历
int top; //栈顶指针
}seqstack;

void push(seqstack* s,bintree t) //进栈
{
s->data[++s->top]=t;
}

bintree pop(seqstack* s) //出栈
{
if(s->top!=-1) //非递归遍历中,top初始值为-1
{
s->top--;
return (s->data[s->top+1]);
}
else
return NULL;
}


//按照前序遍历顺序建立一棵给定的二叉树

void createbintree(bintree* t)
{
char ch;
if((ch=getchar())==' ')
*t=NULL;
else
{
*t=(bintnode*)malloc(sizeof(bintnode)); //产生二叉树根结点
(*t)->data=ch;
createbintree(&(*t)->lchild); //递归实现左子树的创建
createbintree(&(*t)->rchild); //递归实现右子树的创建
}
}


//二叉树前序遍历 非递归 实现

void preorder1(bintree t)
{
seqstack s;//栈
s.top=-1; //top初始值为-1
while((t)||(s.top!=-1)) // 当前 处理的 子树 不为空,或栈不为空,则循环
{
while(t)
{
cout<<t->data<<" "; //访问当前子树根结点
s.top++;
s.data[s.top]=t; //当前子树根结点进栈(因为还要访问右子树)
t=t->lchild; //访问此根结点 左孩子
} //循环直到遍历完 当前子树 根结点,和其 左 孩子
if(s.top>-1)
{
t=pop(&s); //当前子树跟结点出栈
t=t->rchild; //访问其右孩子
}
}
}

//二叉树中序遍历 非递归 算法

void inorder1(bintree t)
{
seqstack s;
s.top=-1;
while((t!=NULL)||(s.top!=-1))
{
while(t)
{
push(&s,t);
t=t->lchild; //子树根结点全部进栈
}
if(s.top!=-1)
{
t=pop(&s);
cout<<t->data<<" "; //输出根结点,其实也就是左孩子或右孩子(没有孩子的根结点是它父亲的左或右孩子)
t=t->rchild; //进入右孩子访问
}
}
}


//后序遍历 非递归 实现

void postorder1(bintree t)
{
seqstack s;
s.top=-1;
while((t)||(s.top!=-1))
{
while(t)
{
s.top++;
s.data[s.top]=t; //子树根结点进栈
s.tag[s.top]=0; //设此根结点标志初始化为0,表示左右孩子都没访问,当访问完左子树 tag 变为1
t=t->lchild; //进入左子树访问。(左子树根结点全部进栈)
}
while((s.top>-1)&&(s.tag[s.top]==1))
{
t=s.data[s.top];
cout<<t->data<<" "; //没有孩子的根结点,也就是它父亲的左孩子或右孩子
s.top--;
}
if(s.top>-1)
{
t=s.data[s.top];
s.tag[s.top]=1; //进入右子树 前,标志tag变为1
t=t->rchild; //进入右子树
}
else
t=NULL;
}
}


int main()
{
bintree tree;
cout<<"输入根结点:";
createbintree(&tree);
cout<<"\n前序非递归遍历二叉树:";
preorder1(tree);
cout<<"\n-----------------------------\n";
cout<<"\n中序非递归遍历二叉树:";
inorder1(tree);
cout<<"\n----------------------------\n";
cout<<"\n后序非递归遍历二叉树:";
postorder1(tree);
cout<<endl;
}

例如:

输入:ABC D

输出:输入根结点:ABC D

前序非递归遍历二叉树:A B C D

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

中序非递归遍历二叉树:C B D A

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

后序非递归遍历二叉树:C D B A



qdrnocking 2010-10-11
  • 打赏
  • 举报
回复
还没看你的代码,但是

如果是如ABCDE,CBDEA,这个结果应该是无法构成一颗二叉树,问题出在DE在先、后序上遍历没有变化。

这是因为从这两个遍历结果可以看出A是根节点,B一定是A的左孩子,而C则如楼主所说是B的孩子但不能确定

是左还是右;问题是DE在先序和后序遍历过程没有发生变化,就不清楚他们的关系。

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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