卡特兰数应用 pku OJ ID:1095

pku OJ 的第1095题,有关卡特兰数与二叉树的括号表示。

Description

We can number binary trees using the following scheme: 
The empty tree is numbered 0. 
The single-node tree is numbered 1. 
All binary trees having m nodes have numbers less than all those having m+1 nodes. 
Any binary tree having m nodes with left and right subtrees L and R is numbered n such that all trees having m nodes numbered > n have either Left subtrees numbered higher than L, or A left subtree = L and a right subtree numbered higher than R. 

The first 10 binary trees and tree number 20 in this sequence are shown below: 

Your job for this problem is to output a binary tree when given its order number. 

Input

Input consists of multiple problem instances. Each instance consists of a single integer n, where 1 <= n <= 500,000,000. A value of n = 0 terminates input. (Note that this means you will never have to output the empty tree.)

Output

For each problem instance, you should output one line containing the tree corresponding to the order number for that instance. To print out the tree, use the following scheme: 

A tree with no children should be output as X. 
A tree with left and right subtrees L and R should be output as (L')X(R'), where L' and R' are the representations of L and R. 
If L is empty, just output X(R'). 
If R is empty, just output (L')X. 

Sample Input

1
20
31117532
0

Sample Output

X
((X)X(X))X
(X(X(((X(X))X(X))X(X))))X(((X((X)X((X)X)))X)X)


将所有二叉树按上图中示例编号:
1.空树编号为0,只有一个节点的树编号为1。
2.m个节点的二叉树的编号均小于m+1个节点的二叉树。
3.m个节点的二叉树的编号为n,满足:所有编号大于n的m个节点的二叉树要么左子树编号比它左子树编号高,要么左子树编号一样,右子树编号比它右子树高。


程序任务为:输入一系列二叉树的编号,分行输出它们对应的树。如果输入为0,则结束。

输出要求:二叉树输出为(L)X(R)的格式,L为左子树,R为右子树。如果左子树为空,则输出格式为X(R);如果右子树为空,输出格式为:(L)X。

示例输入:

1

20

31117532

0

示例输出:

X
((X)X(X))X
(X(X(((X(X))X(X))X(X))))X(((X((X)X((X)X)))X)X)


完成程序。


程序用到了卡特兰数的应用,即n个顶点的二叉树的不同形态数为第n个卡特兰数。

程序接收一系列的输入,直到0结束,并依次输出对应的树。注意在OJ上对程序有着严格的检查,由于是先输入完再统一输出,利用数组存储输入会有数组越界的可能,无论你定义的多大,OJ都会提示Runtime Error(RE)。故应使用链表来存储。

程序首先计算卡特兰数存储以方便使用。对于每一个输入,计算该二叉树为几个节点以及在相同的节点中编号为多少。利用这两个参数调用相应函数,函数通过计算左子树和右子树的对应值来递归调用自身。

程序如下:

(编程语言为C,在OJ中已AC,如有错误,请留言咨询。)

#include "stdio.h"
#include "malloc.h"
#define max 25
int C[max];//卡特兰数,C18基本达到了要求500,000,000.
typedef struct node{
	int number;
	struct node * next;
}*Node;
void catalan(int C[])
{
	int n,i;
	C[0]=1;
	C[1]=1;
	for (n=2; n<max; n++)
	{
		C[n]=0;
		for (i=0; i<n; i++)
		{
			C[n] += C[i]*C[n-1-i];
		}
	}
}
void printcatalan(int n, int number)
//输出 n个节点的,编号为number的树
{
	int i=0;
	if(n == 0)
		return;
	if(n == 1)
	{
		printf("X");
		return;
	}

	while(number >=C[i]*C[n-1-i])
	{
		number -= C[i]*C[n-1-i];
		i++;
	}

	if(i>0)
		printf("(");
	printcatalan(i,number/C[n-1-i]);//输出左子树
	if(i>0)
		printf(")");

	printf("X");//输出中间节点

	if(n-1-i>0)
		printf("(");
	printcatalan(n-1-i,number%C[n-1-i]);//输出右子树
	if(n-1-i>0)
		printf(")");
}
int main()
{
	
	int number;
	int n=0;
	int i=0,j=0;
	Node p;
	Node N,q;
	N = (Node)malloc(sizeof(struct node));
	N->next=NULL;
	N->number=0;
	q = N;
	catalan(C);
	scanf("%d",&number);
	while(number!=0)
	{
		p = (Node)malloc(sizeof(struct node));
		p->next=NULL;
		q->next = p;
		q = q->next;
		p->number = number;
		scanf("%d",&number);
	}
	q = N;
	
	while(q->next != NULL)
	{
		q = q->next;
		number = q->number;
		n=0;
		while(number>=C[n])
		{
			number -= C[n];
			n++;
		}
		printcatalan(n,number);//n个节点的,编号为number的树
		printf("\n");
	}
	//第n个卡特兰数的第number个数,0<=number<=C[n]-1
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值