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

完全二叉树简介

  • 完全二叉树是指,所有节点最多有两个叉
  • 并且每层都得从左向右排列
  • 必须上一层排满了,才能排下一层
  • 度是指,当前节点有几个子节点。在二叉树中,只可能有三种不同的度节点
    • 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 = 1,edgeNum = 0
  • 之后,在这棵树上,每添加一个点,必须要添加一个边。例如再添加n个点,那么nodeNum = n + 1,edgeNum = 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 + 1 和 nodeNum = n0 + n1 + n2 + n3 + n4

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

即叶子节点数量n0:n0 = 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 + 1即nr = 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。
相关推荐
不会就选b1 分钟前
算法日常・每日刷题--<动态规划>22
算法·动态规划
释厄6236 分钟前
字画同体论——字即画·几何即字·漫画与小说=文本层
人工智能·算法
沫璃染墨23 分钟前
从零入门数据结构与算法(一):复杂度分析——从算法效率到时间与空间复杂度
c语言·开发语言·数据结构·笔记·算法·飞书
熊猫钓鱼>_>1 小时前
面试出现 606 次的第 K 大,被拆成三个问题问
算法·面试·职场和发展·校招·面经·oj·ai生成
xuxigifxfh1 小时前
牛客:BISHI2 【模板】栈的操作
java·开发语言·windows·算法
aqiu1111111 小时前
【C++算法打怪专栏】LeetCode 402. 移掉 K 位数字(单调栈 + 贪心)
c++·算法·leetcode
糖果豆豆2 小时前
对象是字段,还是关系?集合论和范畴论吵了三十年,答案是两个都对
算法·架构
第六种自由2 小时前
[路飞]_Leetcode 22. 括号生成
javascript·算法·leetcode
isyoungboy2 小时前
事件驱动状态机与循环扫描状态机:两种计算模型的比较研究
算法·状态机
行者全栈架构师2 小时前
【鸿蒙心迹】从手机到平板、折叠屏——多端适配自查清单与踩坑实录(HarmonyOS 7.x)
前端·算法·架构