完全二叉树的理解和相关公式推导

完全二叉树简介

  • 完全二叉树是指,所有节点最多有两个叉
  • 并且每层都得从左向右排列
  • 必须上一层排满了,才能排下一层
  • 是指,当前节点有几个子节点。在二叉树中,只可能有三种不同的度节点
    • 2度节点,即有左右两个子元素的节点
    • 1度节点,只有一个子元素的节点,由于完全二叉树的特性,1 度节点最多只有一个
    • 0度节点,即叶子节点。叶子节点最多出现在后两层。

如下是14个节点的完全二叉树。

js 复制代码
           0
         /   \
        /     \
       /       \
      /         \
     1           2
    / \         / \
   /   \       /   \
  3     4     5     6
 / \   / \   / \   /
7   8 9  10 11 12 13

其实上面的完全二叉树,是可以从上往下,从左往右,放入到一个数组中,为了方便表示,上图直接把节点的值写成了数组下标。

几个公式和其证明

nodeNum = edgeNum + 1

在任何不循环的树中,其节点数量nodeNum 和边数量edgeNum的关系是 nodeNum = edgeNum + 1

  • 例如当前这棵树只有一个节点,那么 nodeNum = 1edgeNum = 0
  • 之后,在这棵树上,每添加一个点,必须要添加一个边。例如再添加n个点,那么nodeNum = n + 1edgeNum = n
  • 通过上述两个和n相关的关系式,可以得出 nodeNum = edgeNum + 1

叶子节点推算公式 N0 = (n-1)*Nn + (n-1)*Nn-1 + ... + 2*N3 + N2 + 1

在一棵度最大为 4(这里用 n 表示,比较好,但是那个数学公式用代码表述比较麻烦,所以先用实数 4 举例)的树中,假设

  • 0 度节点有n0
  • 1 度节点有n1
  • 2 度节点有n2
  • 3 度节点有n3
  • 4 度节点有n4

那么总节点数nodeNum的值为nodeNum = n0 + n1 + n2 + n3 + n4 从边的角度讲:

  • 0 度节点有 0 个边
  • 1 度节点有 1 个边
  • 2 度节点有 2 个边
  • 3 度节点有 3 个边
  • 4 度节点有 4 个边

所以 edgeNum = 0*n0 + 1*n1 + 2*n2 + 3*n3 + 4*n4

又有nodeNum = edgeNum + 1nodeNum = n0 + n1 + n2 + n3 + n4

可以得出 1*n1 + 2*n2 + 3*n3 + 4*n4 + 1 = n0 + n1 + n2 + n3 + n4

即叶子节点数量n0n0 = 3*n4 + 2*n3 + n2 + 1

这个公式适用于任何多叉树叶子节点的计算,

  • 3 叉树为:n0 = 2*n3 + n2 + 1
  • 5 叉树为:n0 = 4*n5 + 3*n4 + 2*n3 + n2 + 1
  • n 叉树为:N0 = (n-1)*Nn + (n-1)*Nn-1 + ... + 2*N3 + N2 + 1(这里因为 md 不能用下标 n 这种表示,所以把 n 大写了。)

二叉树叶子节点公式 n0=n2+1

其中,二叉树的情况为:

节点的情况

  • 0 度节点有n0
  • 1 度节点有n1
  • 2 度节点有n2

边的情况:

  • 0 度节点有 0 个边
  • 1 度节点有 1 个边
  • 2 度节点有 2 个边

按照上述推导以后得出 n0 = n2 + 1,即叶子节点2度节点多一个

二叉树左子树位置计算公式 nl = 2n + 1

假设现在有个一个节点,它在数组中下标为n,它和其左子树下标nl的关系是nl = 2n + 1,那右子树nr就是nl + 1nr = 2n + 2。证明如下。

设想这棵二叉树只绘制填充到当前元素左子树被填充的情况(可以参考成下图,5 就是此时的 n)。

js 复制代码
           0
         /   \
        /     \
       /       \
      /         \
     1           2
    / \         / \
   /   \       /   \
  3     4     5     6
 / \   / \   /
7   8 9  10 11
  • 所有后续兄弟节点都没有子元素,即都是叶子节点

  • 所有前序兄弟都被填满,即所有前续兄弟都是2度节点

  • 叶子节点数量 n0: n0 = 后续兄弟数量 + 前序兄弟 * 2 + 1,+1 是因为本节点的左子节点也是叶子节点。

  • 此时nl的位置就是当前节点位置加上所有叶子节点的数量即:nl = n + n0(等式 1)

  • 2度节点的数量为n2: 又由于当前节点之前所有节点都被填充满了,所以当前节点之前的节点,都是2度节点,那就是从 0 到 n-1,总共有 n 个,即n2 = n(等式 2)

  • 我们从上节推算出了二叉树中叶子节点2度节点的数量关系为n0 = n2 + 1(等式 3)

带入上述等式

js 复制代码
nl = n  + n0
n2 = n;
n0 = n2 + 1;
// 带入等式:
nl = n  + n2 + 1
   = n + n + 1
   = 2n + 1

那么右子树的位置就是 2n+2,n 的父元素的位置就是(n - 1) / 2,对结果向下取整。

完全二叉树的层高:log2(n+1)取上界

  • 在完全二叉树中,第 l 层(层数从 1 开始计算),最多存放 2^(l-1) 个节点。例如第 1 层有 1 个节点(根节点),第 2 层有 2 个节点,第 3 层有 4 个节点。
  • 那么本层最后一个元素的就是第 1 + 2 + 4 + ... + 2^(l-1)个元素,即2^l - 1
  • 上一层最后一个元素就是第2^(l-1) - 1个。
  • 那么第 n 层元素存放的就是 第2^(l-1)2^l - 1个。

例如当前有个元素,它的下标为 n,那么,它就是第n+1个元素,假设它所处的层级是第 l 层,就有表达式:2^(l-1) <= n+1 < 2^l(注意,2^l 即下层第一个元素),取对数得l-1 <= log2(n+1) < l

即 l 层高为:log2(n+1)的上界(如果不是整数,就向上取整,如果是整数,就+1)。eg:

  • 索引为 6 的元素,层高为 log2(6+1)的上界,2.88,取上界为 3。
  • 索引为 7 的元素,层高为 log2(7+1)的上界,3,取上界为 4。
相关推荐
仙俊红40 分钟前
LeetCode每日一题,20250914
算法·leetcode·职场和发展
风中的微尘7 小时前
39.网络流入门
开发语言·网络·c++·算法
西红柿维生素8 小时前
JVM相关总结
java·jvm·算法
ChillJavaGuy10 小时前
常见限流算法详解与对比
java·算法·限流算法
sali-tec10 小时前
C# 基于halcon的视觉工作流-章34-环状测量
开发语言·图像处理·算法·计算机视觉·c#
你怎么知道我是队长11 小时前
C语言---循环结构
c语言·开发语言·算法
艾醒11 小时前
大模型面试题剖析:RAG中的文本分割策略
人工智能·算法
纪元A梦13 小时前
贪心算法应用:K-Means++初始化详解
算法·贪心算法·kmeans
_不会dp不改名_14 小时前
leetcode_21 合并两个有序链表
算法·leetcode·链表
mark-puls14 小时前
C语言打印爱心
c语言·开发语言·算法