数据结构:N个节点的二叉树有多少种(Number of Binary Trees Using N Nodes)

目录

[N个无标签节点的二叉树有多少种形态?(Unlabelled N nodes)](#N个无标签节点的二叉树有多少种形态?(Unlabelled N nodes))

[n = 0:](#n = 0:)

[n = 1:](#n = 1:)

[n = 2:](#n = 2:)

[n = 3:](#n = 3:)

发现规律,建立递推公式

[N个有标签节点的二叉树有多少种形态?(Labelled N Nodes)](#N个有标签节点的二叉树有多少种形态?(Labelled N Nodes))

第一步:选定一个结构

第二步:给结构贴上标签

第三步:组合


我们将一步步推导拥有 N 个节点的二叉树形态数量。

这里必须先澄清一个核心问题:"节点是否相同?"

1. 无标签节点 (Unlabelled Nodes):所有节点都是一模一样的,我们只关心树的结构。

比如 A(B, C)B(A, C),如果只看结构,它们是不同的(根不同)。

但如果把 A, B, C 三个节点看作是完全一样的"小球",我们只关心能搭出多少种不同的"架子"。

2. 有标签节点 (Labelled Nodes):每个节点都是独一无二的,

比如它们的值是 1, 2, ..., N。在这种情况下,即使两个树的结构完全相同,只要节点上的值(标签)分布不同,它们就是两棵不同的树。

数据结构:树(Tree)-CSDN博客

我们先从更根本、也更难的无标签节点问题开始。


N个无标签节点的二叉树有多少种形态?(Unlabelled N nodes)

这个问题本质上是在问:

"用N个一模一样的节点,可以搭出多少种不同的二叉树结构?"

我们设 h(n) 是拥有 n 个节点的二叉树的形态总数。

我们没有现成的公式,所以从最简单的情况开始,寻找规律。

n = 0:

0个节点。有多少种形态?

  • 只有一种,那就是空树 (Empty Tree)。所以 h(0)=1

注意:这个基础情况非常重要,是后续所有推导的基石。很多人会误以为是0。但"空树"本身是一种确定的状态。

n = 1:

1个节点。只有一种形态:一个单独的根节点。所以 h(1)=1。

cpp 复制代码
n=0:   ∅

n=1:   ●

n = 2:

2个节点。我们必须选择一个作为根节点,剩下1个节点。

这1个节点可以是根的左孩子,也可以是根的右孩子。因为二叉树严格区分左右,所以这是两种不同的结构。所以 h(2)=2。

cpp 复制代码
Case 1:     ●         Case 2:    ●
            /                     \
          ●                        ●

n = 3:

3个节点。同样,我们选择一个作为根节点,剩下2个节点需要安排。

这两个节点如何分布在根的左右子树中呢?

cpp 复制代码
1.    ●       2.    ●       3.    ●       4.    ●       5.    ●
       \           / \          /             /               \
        ●         ●   ●       ●             ●                 ●
         \                   /               \                 /
          ●                 ●                 ●               ●
  • 情况1: 左子树有2个节点,右子树有0个节点。

    • 左子树的2个节点有多少种形态?根据我们上面算出的 h(2),有2种。

    • 右子树的0个节点有多少种形态?根据 h(0),有1种(空树)。

    • 根据乘法原理,这种情况的总形态数是 h(2) × (0) = 2 种。

这个例子里的乘法原理,其实就是组合计数里的一个基本原则:

如果一个结果需要经过 两步(或多步)独立的选择 来确定,并且每一步的选择彼此独立,那么总的可能数 = 各步骤可能数的乘积。

为什么相乘?

  1. 先选择左子树的形态:有 2 种可能。

  2. 再选择右子树的形态:有 1 种可能。

这两步是独立的------选了哪一种左子树,并不影响右子树的形状可能性。


  • 情况2: 左子树有1个节点,右子树有1个节点。

    • 左子树1个节点有 h(1) = 1 种形态。

    • 右子树1个节点有 h(1) = 1 种形态。

    • 总形态数是 h(1) × (1) = 1 种

  • 情况3: 左子树有0个节点,右子树有2个节点。

    • 左子树0个节点有 h(0) = 1 种形态。

    • 右子树2个节点有 h(2) = 2 种形态。

    • 总形态数是 h(0) × (2) = 2 种。

cpp 复制代码
Case 1:  左 0,右 2(T(0)×T(2)=1×2 种)
    ●
     \
      ●
       \
        ●

    ●
     \
      ●
     /
    ●

Case 2:  左 1,右 1(T(1)×T(1)=1×1 种)
    ●
   / \
  ●   ●

Case 3:  左 2,右 0(T(2)×T(0)=2×1 种)
    ●
   /
  ●
   \
    ●

    ●
   /
  ●
 /
●

把所有情况加起来,就是 h(3) 的总数:

h(3) = h(2) × (0) +h(1) × (1) + h(0) × (2) = 2 + 1 + 2 = 5 种。


发现规律,建立递推公式

通过 h(3) 的推导,我们发现了一个普适的模式。对于一棵有 n 个节点的树:

  1. 我们取出一个节点作为根。剩下 n−1 个节点。

  2. 这 n−1 个节点将被分配到左、右两个子树中。

  3. 我们可以枚举左子树的节点数量。假设左子树有 i 个节点(i 可以从 0 到 n−1)。

  4. 那么,右子树就必须有 (n−1)−i 个节点。

  5. 左子树自身有 h(i) 种形态,右子树自身有 h(n−1−i) 种形态。这两种形态的组合是独立的,所以根据乘法原理,当左子树有 i 个节点时,总的形态数是 h(i)cdoth(n−1−i)。

  6. 最后,我们把所有可能的 i 的情况(从 i=0 到 i=n−1)全部加起来,就得到了 h(n) 的总数。

这就得到了我们的递推公式:

展开来看就是:

你可能不认识上面这个公式,但在数学领域,这个序列非常非常有名。由这个递推公式定义的序列,就是卡特兰数 (Catalan Number)

卡特兰数的通项公式 (Closed-Form Formula)

递推公式虽然精确,但每次计算都需要知道前面所有的值,效率很低。

数学家们已经找到了它的通项公式。 (这个通项公式的推导需要用到"生成函数"等高等数学技巧,远超出了数据结构的范畴,所以我们这里不进行第一性推导,而是直接给出结论并解释它。)

卡特兰数的第 n 项(从第0项开始)为:

这里 binom2nn 是组合数,读作 "2n choose n",代表从 2n 个不同物品中选出 n 个的方案数。

所以,N个无标签节点的二叉树形态数量就是第N个卡特兰数 C_N。


N个有标签节点的二叉树有多少种形态?(Labelled N Nodes)

这个问题比上一个要简单,因为它可以在上一个问题的基础上直接推导。

第一步:选定一个结构

我们已经知道,N个节点能组成的二叉树结构有 C_N 种。

我们先从这 C_N 种结构中随便选出一种。 这个结构有 N 个"空位"(节点位置)。

第二步:给结构贴上标签

现在我们有 N 个不同的标签(比如数字 1, 2, ..., N)。要把这 N 个标签贴到我们选定的那个结构上的 N 个"空位"里。

  • 第1个标签,有 N 个位置可以贴。

  • 第2个标签,剩下 N−1 个位置可以贴。

  • ...

  • 最后一个标签,只剩下1个位置。

  • 这是一个典型的全排列 (Permutation) 问题。将 N 个不同的标签安排到 N 个不同的位置,总的方案数是 N!

第三步:组合

我们有 C_N 种不同的结构。对于每一种结构,我们都有 N!种不同的贴标签方法。

根据乘法原理,总的形态数就是:

(总形态数) = (结构数) × (每种结构的标签方法数)

我们把卡特兰数的通项公式代入:

相关推荐
艾伦~耶格尔43 分钟前
【数据结构进阶】
java·开发语言·数据结构·学习·面试
快去睡觉~3 小时前
力扣400:第N位数字
数据结构·算法·leetcode
汤永红5 小时前
week1-[循环嵌套]画正方形
数据结构·c++·算法
pusue_the_sun5 小时前
数据结构——顺序表&&单链表oj详解
c语言·数据结构·算法·链表·顺序表
yi.Ist6 小时前
图论——Djikstra最短路
数据结构·学习·算法·图论·好难
数据爬坡ing6 小时前
过程设计工具深度解析-软件工程之详细设计(补充篇)
大数据·数据结构·算法·apache·软件工程·软件构建·设计语言
呼啦啦啦啦啦啦啦啦8 小时前
【Java】HashMap的详细介绍
java·数据结构·哈希表
qq_513970448 小时前
力扣 hot100 Day74
数据结构·算法·leetcode
John.Lewis9 小时前
数据结构初阶(15)排序算法—交换排序(快速排序)(动图演示)
c语言·数据结构·排序算法