完全二叉树、完美二叉树、完满二叉树、计算完全二叉树的结点

2023-11-03 03:59

本文主要是介绍完全二叉树、完美二叉树、完满二叉树、计算完全二叉树的结点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 完美二叉树、完全二叉树、完满二叉树
    • 一、完美二叉树(Perfect Binary Tree)
      • 完美二叉树的定义:
    • 二、完全二叉树**(Complete Binary Tree)**
      • 完全二叉树的定义:
    • 完美二叉树和完全二叉树:
    • 三、完满二叉树**(Full Binary Tree)**
    • 四、如何计算完全二叉树的结点数?
      • [222. 完全二叉树的节点个数](https://leetcode.cn/problems/count-complete-tree-nodes/)
        • 复杂度分析:

完美二叉树、完全二叉树、完满二叉树

一、完美二叉树(Perfect Binary Tree)

对于完美二叉树,我们常用的是另一个名称:满二叉树

完美二叉树的定义:

完美二叉树是一种特殊的完全二叉树,每层都是满的,像一个稳定的三角形

在这里插入图片描述

二、完全二叉树**(Complete Binary Tree)**

完全二叉树的定义:

全二叉树从根结点到倒数第二层满足完美二叉树,最后一层可以不完全填充,其叶子结点都靠左对齐。

在这里插入图片描述

其实理解完全二叉树可以借助于**栈(stack)**的思想。

具体就是我们可以将一棵完美二叉树的所有节点按照编号1…15的顺序依次入栈。然后对栈每一次出栈,栈里保存的结点集构造一棵二叉树都是一棵完全二叉树

完美二叉树和完全二叉树:

下图是一棵完美二叉树:

现在将编号为15, 14, …, 9的叶子结点从右到左依次拿掉或者拿掉部分,则是一棵完全(Complete)二叉树
在这里插入图片描述

例如将上图中的编号为15, 14, 13, 12, 11叶子结点都拿掉(从右到左的顺序):

在这里插入图片描述

但是如果不是依次拿掉就不满足完全二叉树

例如将上图编号15,14,13,11叶子结点都拿掉(从右到左的顺序):

在这里插入图片描述

那可以把它变成完全二叉树吗?

要不就是在拿掉编号11的时候也拿掉编号12,要不就是让编号11座位编号5的右孩子,则变成一棵完全二叉树

三、完满二叉树**(Full Binary Tree)**

所有非叶子结点的度都是2。(只要你有孩子,你就必然是有两个孩子。)

四、如何计算完全二叉树的结点数?

222. 完全二叉树的节点个数

这题其实很简单,但是为了达到较高效的时间复杂度,我们可以用到上面介绍到的完满二叉树

  • 如果是求一棵普通二叉树的结点数,只需要这样遍历就能得到结果,时间复杂度为 O(N):
public int countNodes(TreeNode root) {if (root == null) return 0;return 1 + countNodes(root.left) + countNodes(root.right);
}
  • 如果是求一棵满二叉树,节点总数和树的高度呈指数关系:
public int countNodes(TreeNode root) {int h = 0;// 计算树的高度while (root != null) {root = root.left;h++;}// 节点总数就是 2^h - 1return (int)Math.pow(2, h) - 1;
}
  • 完全二叉树比普通二叉树特殊,但又没有满二叉树那么特殊,计算它的节点总数,可以说是普通二叉树和满二叉树的结合版
public int countNodes(TreeNode root) {TreeNode l = root, r = root;// 沿最左侧和最右侧分别计算高度int hl = 0, hr = 0;while (l != null) {l = l.left;hl++;}while (r != null) {r = r.right;hr++;}// 如果左右侧计算的高度相同,则是一棵满二叉树if (hl == hr) {return (int)Math.pow(2, hl) - 1;}// 如果左右侧的高度不同,则按照普通二叉树的逻辑计算return 1 + countNodes(root.left) + countNodes(root.right);
}

结合刚才针对满二叉树和普通二叉树的算法,上面这段代码应该不难理解,就是一个结合版,但是其中降低时间复杂度的技巧是非常微妙的

复杂度分析:

这个算法的时间复杂度是 O(logN*logN),这是怎么得到的呢?

直觉感觉好像最坏情况下是 O(N*logN) 吧,因为之前的 while 需要 logN 的时间,最后要 O(N) 的时间向左右子树递归:

return 1 + countNodes(root.left) + countNodes(root.right);

但是关键点在于,这两个递归只有一个会真的递归下去,另一个一定会触发 hl == hr 而立即返回,不会递归下去

因为一棵完全二叉树的两棵子树,至少有一棵是满二叉树,如图所示:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

很明显,由于完全二叉树的性质,其子树一定有一棵是满的,所以一定会触发 hl == hr,只消耗 O(logN) 的复杂度而不会继续递归。

综上,算法的递归深度就是树的高度 O(logN),每次递归所花费的时间就是 while 循环,需要 O(logN),所以总体的时间复杂度是 O(logN*logN)。

所以说,「完全二叉树」这个概念还是有它存在的原因的,不仅适用于数组实现二叉堆,而且连计算节点总数这种看起来简单的操作都有高效的算法实现。

这篇关于完全二叉树、完美二叉树、完满二叉树、计算完全二叉树的结点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/335438

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

HDU 2159 二维完全背包

FATE 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务。久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级。现在的问题是,xhd升掉最后一级还需n的经验值,xhd还留有m的忍耐度,每杀一个怪xhd会得到相应的经验,并减掉相应的忍耐度。当忍耐度降到0或者0以下时,xhd就不会玩这游戏。xhd还说了他最多只杀s只怪。请问他能

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr