100分,求这个程序,二叉树的递归,请进来看看题目。各位,这个题目我已经花了很多时间,但是解不了,只能请大家帮忙了

besthyq 2004-11-07 07:13:25
题意描述:
  转眼之间,新学期已经过去几个月了,F大学计算机系的W教授决定对他的学生进行一次测试。为了测试学生对树结构的认识,同时也检验他们的编程能力,教授把测试的内容定为:要求学生们编程按编号顺序打印出节点个数不少于m的所有二叉树。
  二叉树编号规则如下:
  仅有一个元素的树编号为1。
  当满足以下条件之一时,定义二叉树a的编号比b大:
    1. a的节点数比b多。
    2. 若a的节点数与b相等,且a的左子树编号比b的左子树大。
    3. a的节点数和左子树编号都和b相等,且a的右子树编号比b的右子树大。
  二叉树的元素用大写X表示。
    
  例如: 
  打印二叉树的格式为:
  ( 左子树 ){若左子树为空,则省略} X{根} ( 右子树 ){若右子树为空,则省略}
  例如在上图中,编号为2 的树可表示为:X(X);
         编号为3 的树可表示为:(X)X;
         编号为5 的树可表示为:X((X)X);
  当然当m较大时,检验答案对错的工作也是很繁重的,所以教授只打算对其中的若干个编号的二叉树进行抽查,他想麻烦你在测试开始前把标准答案先准备好(教授的测试卷会事先交给你)。

输入:
  输入文件为教授的测试卷,至少1行,至多10行,每行一个数N(1<=N<=10^8),即要抽查的二叉树的编号,以零结束。

输出:

  输出文件是你求出的标准答案,对每一个编号输出其对应的二叉树,每个二叉树占一行,零不用输出。

样例输入(tree.in):

  2
  5
  0

样例输出(tree.out):

  X(X)
  X((X)X)

思路:

  这是一道与树有关的题目,看到树,首先想到的是用递归的方法。
  首先继续写出几种可能的树:
  
  由此可以想到,一棵有N个节点的树是由一个根节点加上一个曾在它之前出现过的节点数为1到N-1之间的树作为左子树或右子树(也可以为空,节点数为0)(如图,第(10)号树中"包"着第(5)号树,第(5)号树中又"包"着第(3)号树)。设用aXb表示有N个节点的树的所有情况,a表示左子树有a个节点,b表示右子树有b个节点,X是根节点,那么令a=0 N-1,b=N-1-a,用aXb就可以表示有N个节点的树的所有情况。例如,有5个节点的树是由0X4,1X3,2X2,3X1,4X0几部分组成。
  知道了N个节点的树的组成,就可以算出节点为N的树的总数,这用递推可以实现。F(N)表示节点数为N的树的总数。计算前先令F(1)=1,F(0)=1,从F(2)开始递推。
           
  把树的总数累加起来,就得到树的编号,如有5个节点第一种树的编号就是F(1)+F(2)+F(3)+F(4)+1,知道了树的编号,便可以知道树的节点个数了。(经过计算,编号为10^8的树节点不超过20个,数据存储用字符串变量就可以了)。
  为了说明这个问题,我来举一个例子:假设我们要求编号为44的树,由以上方程可以知道44-(F(1)+F(2)+F(3)+F(4))=22<F(5),所以44号树有5个点,并且可知,第44号树是所有5个节点的树中的第22种。对于5个点的树,就有上述0X4,1X3,2X2,3X1,4X0,几种情况,0X4的树有14种(F(a) F(b)),1X3有5种,2X2有4种……所以第22种情况就是2X2的树,并且是2X2树中的第22-14-5=3种,在把左右子树分别递归计算,设t=3,左子树就是2个点(a=2)的树中的第((t-1)div F(b))+1种情况,右子树就是2个点(b=2)的树种的第((t-1)mod F(b))+1种情况。依次递归。e

...全文
239 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
besthyq 2004-11-07
  • 打赏
  • 举报
回复
恩,,谢谢你。。。

加你分。
yanglight 2004-11-07
  • 打赏
  • 举报
回复

样例输入(tree.in):

  2
  5
  0

样例输出(tree.out):

  X(X)
  X((X)X)
-------------------------
那不是你的要求吗??

besthyq 2004-11-07
  • 打赏
  • 举报
回复
问你下,,为什么要从外部读入文件,这样在这里有什么好出呢?

yanglight 2004-11-07
  • 打赏
  • 举报
回复
另外如果你的测试数字很大(〉30000),F()函数用注释内的内容
yanglight 2004-11-07
  • 打赏
  • 举报
回复
你只要在程序目录下建一个tree.in的文件(注:扩展名是in)然后用记事本打开,写入要测试的数据(数据以回车隔开)文件最后以-1结尾。
besthyq 2004-11-07
  • 打赏
  • 举报
回复
你好,,我还不会从外部调用tree in文件

我是刚才算法的新手,,请教你了,,,这个是怎么回事呢?
yanglight 2004-11-07
  • 打赏
  • 举报
回复
不会地,我测试了(VC6)
tree.in文件内容
---------------------
1
23
57
99
234
-1
------------
结果如下
------------------------
1
X
23
X(X(X(X(X))))
57
((X)X((X)X))X
99
X(((X)X((X)X))X)
234
X(X(((X(X(X)))X)X))
Press any key to continue
besthyq 2004-11-07
  • 打赏
  • 举报
回复
死循环啊。。。。。。。。。
yanglight 2004-11-07
  • 打赏
  • 举报
回复
看程序呀,
tree.in中数据以-1结尾
lazyboya 2004-11-07
  • 打赏
  • 举报
回复
好像死循环啊.
Squall1009 2004-11-07
  • 打赏
  • 举报
回复
..................
yanglight 2004-11-07
  • 打赏
  • 举报
回复
注意:F()函数中用了两种方法求注释掉的部分用的是递归方法,保留的是一个公式求法(能提高运行效率)。
yanglight 2004-11-07
  • 打赏
  • 举报
回复
//花了三个小时作的,测试通过^-^
#include <iostream.h>
#include <fstream.h>

//已知节点数求最大编号
long C(int m,int n)
{
if(m==n||n==0)return 1;
long r=1;
for(int i=0;i<n;i++)
{
r*=m-i;
}
for(int j=0;j<n;j++)
r/=j+1;
return r;
}
long F(int n)
{
return C(2*n,n)/(n+1);
/*
if(n==0||n==1)return 1;
else
{
long r=0;
for(int i=0;i<n;i++)
{
r+=F(i)*F(n-1-i);
}
return r;
}*/
}
//已知编号求节点数
int nOfNode(long n)
{
if(n==0)return 0;
long left=n;
int i=1;
while(F(i)<left)
{
left-=F(i);
i++;
}
return i;

}

void printTree(int m,long n)
{
if(m==0)return;
long left=n;
//左边的编号数
long i=0;
//左边节点数
int nLeft=nOfNode(i);
while(F(m-1-nLeft)<left)//(((m-1-nLeft)==0?0:F(m-1-nLeft))<left)
{
left-=F(m-1-nLeft);
i++;
nLeft=nOfNode(i);
}


if(nLeft!=0)cout<<"(";
long l=i;

for(int j=1;j<nLeft;j++)
{
l-=F(j);
}
printTree(nLeft,l);
if(nLeft!=0)cout<<")";


cout<<"X";


long nRight=m-1-nLeft;
if(nRight!=0)cout<<"(";
l=left;


printTree(nRight,l);
if(nRight!=0)cout<<")";

}

void process(long n)
{
//求出节点数
int m=nOfNode(n);
//打印这棵树
long l=n;
for(int i=1;i<m;i++)
{
l-=F(i);
}
printTree(m,l);
// cout<<endl;
}

main()
{
long n;
ifstream fin("tree.in");
fin>>n;
while(n!=-1)
{
cout<<n<<endl;
if(n>=1&&n<=100000000)
{
process(n);
cout<<endl;
}
fin>>n;
}
return 0;
}

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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