现在的位置: 首页 > 综合 > 正文

N个结点可构成多少不同的二叉树

2018年04月05日 ⁄ 综合 ⁄ 共 1253字 ⁄ 字号 评论关闭
题目:树的形态
时间限制1000 ms,内存限制256000 kB,代码长度限制8000 B
每行输入一个自然数n,对应输出两行,每行一个数字,分别是:节点为n的二叉树有____种。如果每个节点可能有红、黑两种颜色,有____种。
输入示例:
1
2
输出示例:
1
2
2
8
思路:此题即为Catalan数的应用之一:N个结点可以构成多少不同的二叉树。
针对问题一,设N个结点可以构成f(N)个不同的二叉树,若左子树有M个结点,那么右子树就有N-M-1个结点,此时子树个数分别为(M, N-M-1)的二叉树有f(M) * f(N-M-1)种,而M可以从0取到N-1,所以f(N)=f(0)*f(N-1) + f(1)*f(N-2) + ··· + f(M)*f(N-M-1) + ··· + f(N-1)*f(0),f(0) = 1,f(1) = 1。上式正是Catalan数的计算公式。
Catalan数的计算公式有如下几种:
f(n)=f(n-1)*(4*n-2)/(n+1);
f(n)=C(2n,n)/(n+1) (n=0,1,2,...);
f(n)=C(2n,n)-C(2n,n+1)(n=0,1,2,...);
C(2n,n)是组合数,此处选用红色标出的公式计算。
针对问题二,由于每个结点都可能是红黑色,所以N个结点就有2^N中可能的颜色排列,再乘以上面的二叉树的种类数,即为着色后的二叉树的种类数:2^N * f(N)
#include <iostream>
#include <math.h>
#include <queue>
typedef unsigned long long ULONG;

ULONG Factorial(ULONG N) {
		if (N < 0) return 0;
		ULONG result = 1;
		for (ULONG i = 2; i <= N; ++ i)
			result *= i;
		return result;
}

ULONG Catalan(ULONG N) {
	if (N < 0)  return 0;
	if (N == 0) return 1;
	if (N == 1) return 1;
	ULONG fn = Factorial(N);
	ULONG comb = Factorial(2*N) / (fn * fn);
	return comb / (N + 1);
}

void CatalanReadData() {
	std::queue<int> input;
	int N;
	while (std::cin >> N) {
		input.push(N);
	}
	while (!input.empty()) {
			ULONG cata = Catalan(input.front());
			std::cout << cata << std::endl;
			std::cout << (ULONG)pow((double)2, input.front()) * cata <<std::endl;
			input.pop();
	}
}
PS:有道,机试,2013,校招
参考:
【上篇】
【下篇】

抱歉!评论已关闭.