当前位置: 首页 > news >正文

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

目录

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

n = 0:

n = 1:

n = 2:

n = 3:

发现规律,建立递推公式

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。

n=0:   ∅n=1:   ●

n = 2:

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

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

Case 1:     ●         Case 2:    ●/                     \●                        ●

n = 3:

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

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

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 种。

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!种不同的贴标签方法。

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

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

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

http://www.dtcms.com/a/333145.html

相关文章:

  • Nacos-5--Nacos2.x版本的通信原理
  • 什么是KVM切换器?详解KVM切换器
  • 电子电气架构 --- 线束设计一些事宜
  • 电子电气架构 --- 探索软件定义汽车(SDV)的技术革新
  • 硬件实现webrtc的编解码
  • 【DDIA】第三部分:衍生数据
  • 《Effective Java》第1条:用静态工厂方法代替构造器
  • 扩展卡尔曼滤波EKF、自适应扩展卡尔曼滤波AEKF、HIF/H∞、粒子滤波PF、卡尔曼粒子滤波EKPF在BJDST动态工况下的SOC估计效果
  • TDengine IDMP 高级功能(2. 事件模板)
  • Stability AI技术浅析(二):LDM
  • 【国内电子数据取证厂商龙信科技】如何识别与查杀木马程序
  • 音视频面试题集锦第 23 期
  • 应急救援智能接处警系统——科技赋能应急,筑牢安全防线
  • Day60--图论--94. 城市间货物运输 I(卡码网),95. 城市间货物运输 II(卡码网),96. 城市间货物运输 III(卡码网)
  • PaddleNLP进行Bart文本摘要训练
  • Linux系统——进程与线程
  • PyTorch 进行人脸训练和 Java 实现人脸识别的解决方案
  • 权重迁移笔记
  • Android RxJava 过滤与条件操作详解
  • CPU性能篇-系统的软中断CPU使用率升高如何处理-Day 06
  • Pytest项目_day16(yaml和parametrize结合)
  • 【R语言】更换电脑后,如何在新设备上快速下载原来设备的 R 包?
  • 神经网络、深度学习与自然语言处理
  • Linux程序内存布局分析
  • ROS2 setup.bash和setup.sh区别差异
  • 【JAVA】实现word添加标签实现系统自动填入字段
  • Python匿名函数的具体用法
  • 堕落之主 单机+联机 全DLC 送修改器(Lords of the Fallen)免安装中文版
  • 【机器人-基础知识】ROS常见功能架构
  • 【JAVA高级】实现word转pdf 实现,源码概述。深坑总结