数据结构之判断完全二叉树详解与示例(C,C++)

news2024/11/13 9:30:13

文章目录

    • 一、判断完全二叉树的思路
    • 二、C语言实现
    • 三、C++语言实现
    • 四、总结

在这里插入图片描述


完全二叉树是一种特殊的二叉树,它满足以下两个条件:

每一层(除了最后一层)都被严格地填充了节点。
最后一层的节点都尽可能地靠左对齐。
本文将详细介绍如何判断一个二叉树是否为完全二叉树,并提供C和C++的实现示例。

一、判断完全二叉树的思路

我们可以通过层序遍历(广度优先搜索)的方式来判断一个二叉树是否为完全二叉树。在层序遍历过程中,我们遵循以下步骤:

  1. 如果当前节点有左子树和右子树,则将它们分别加入队列。
  2. 如果当前节点只有左子树,没有右子树,则将左子树加入队列,并在之后的遍历中,所有节点都必须是叶子节点。
  3. 如果当前节点没有子树,则该节点之后的所有节点都必须是叶子节点。
  4. 如果在遍历过程中,出现了不符合上述条件的节点,那么该二叉树就不是完全二叉树。

二、C语言实现

以下是C语言的实现示例:

#include <stdio.h>
#include <stdlib.h>

// 定义二叉树节点结构体
typedef struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
} TreeNode;

// 判断二叉树是否为完全二叉树
int isCompleteBinaryTree(TreeNode *root) {
    if (root == NULL) return 1; // 空树也是完全二叉树

    // 初始化队列
    TreeNode *queue[10000];
    int front = 0, rear = 0;
    queue[rear++] = root;

    // 开始层序遍历
    while (front < rear) {
        TreeNode *cur = queue[front++];

        // 如果遇到空节点,判断后续节点是否都是空节点
        if (cur == NULL) {
            while (front < rear) {
                if (queue[front] != NULL) return 0;
                front++;
            }
        } else {
            // 将左右子树加入队列
            queue[rear++] = cur->left;
            queue[rear++] = cur->right;
        }
    }

    return 1; // 遍历完成,没有发现不符合条件的节点,是完全二叉树
}

// 创建节点
TreeNode* createNode(int val) {
    TreeNode *node = (TreeNode*)malloc(sizeof(TreeNode));
    node->val = val;
    node->left = NULL;
    node->right = NULL;
    return node;
}

int main() {
    // 创建一个示例二叉树
    TreeNode *root = createNode(1);
    root->left = createNode(2);
    root->right = createNode(3);
    root->left->left = createNode(4);
    root->left->right = createNode(5);

    // 判断是否为完全二叉树
    if (isCompleteBinaryTree(root)) {
        printf("该二叉树是完全二叉树。\n");
    } else {
        printf("该二叉树不是完全二叉树。\n");
    }

    return 0;
}

三、C++语言实现

以下是C++的实现示例:

#include <iostream>
#include <queue>

using namespace std;

// 定义二叉树节点结构体
struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

// 判断二叉树是否为完全二叉树
bool isCompleteBinaryTree(TreeNode* root) {
    if (root == nullptr) return true;

    queue<TreeNode*> q;
    q.push(root);

    bool mustBeLeaf = false; // 标记是否到了必须为叶子的阶段

    while (!q.empty()) {
        TreeNode* node = q.front();
        q.pop();

        if (mustBeLeaf) {
            if (node != nullptr) return false; // 如果到了必须为叶子的阶段,还有非叶子节点,则不是完全二叉树
        } else {
            if (node == nullptr) {
                mustBeLeaf = true; // 遇到空节点,后续节点必须都是叶子节点
            } else {
                q.push(node->left);
                q.push(node->right);
            }
        }
    }

    return true; // 遍历完成,没有发现不符合条件的节点,是完全二叉树
}

int main() {
    // 创建一个示例二叉树
    TreeNode *root = new TreeNode(1);
    root->left = new TreeNode(2);
    root->right = new TreeNode(3);
    root->left->left = new TreeNode(4);
     root->left->right = new TreeNode(5);

    // 判断是否为完全二叉树
    if (isCompleteBinaryTree(root)) {
        cout << "该二叉树是完全二叉树。" << endl;
    } else {
        cout << "该二叉树不是完全二叉树。" << endl;
    }

    return 0;
}

四、总结

通过上述C和C++的实现示例,我们可以看到判断一个二叉树是否为完全二叉树的基本方法是使用层序遍历。在遍历过程中,我们通过设置一个标记来区分节点是否应该为叶子节点,从而判断二叉树是否满足完全二叉树的条件。这种方法的时间复杂度为O(n),其中n是二叉树中节点的数量,因为每个节点最多只会被访问一次。

在实际应用中,完全二叉树由于其特殊的结构,常用于堆的实现,因为它可以在数组中有效地表示,同时保持堆的操作效率。理解并掌握判断完全二叉树的方法,对于深入理解二叉树结构和相关算法有重要意义。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1944031.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构 —— B+树和B*树及MySQL底层引擎

数据结构 —— B树和B*树及MySQL底层引擎 B树B*树B树的应用B树在MySQL中的应用MyISAMInnoDB 我们之前学习了B树的基本原理&#xff0c;今天我们来看看B树的一些改良版本——B树和B*树。如果还没有了解过的小伙伴可以点击这里&#xff1a; https://blog.csdn.net/qq_67693066/ar…

【启明智显分享】基于国产Model3芯片的7寸触摸屏助力智慧医疗,电子床头屏提升护理交互

未来医院必然是以信息化为基础&#xff0c;以物联网为特征&#xff0c;以医疗为核心的服务型医院。病房作为医院的重要服务场所&#xff0c;成为智慧医院建设的重要一环。 为提高医护人员与患者的互动交流&#xff0c;给医疗注入智慧元素&#xff0c;让患者享受智能服务&#…

Ins云手机在运营Instagram账号的优势

在数字时代&#xff0c;Instagram成为全球数亿用户的重要社交平台&#xff0c;其超过10亿的用户数量&#xff0c;为企业提供了广阔的营销空间。对于希望拓展海外市场的企业来说&#xff0c;使用Instagram进行引流和推广是一个高效且安全的选择。为了更高效地管理和运营多个Inst…

C#知识|账号管理系统:修改登录密码界面的UI设计

哈喽,你好啊!我是雷工! 本节记录添加修改登录密码界面的过程,以下为练习笔记。 01 效果演示 演示跳转打开修改登录密码子窗体效果: 02 添加窗体 在UI层添加一个Windows窗体,命名为:FrmModifyPwd.cs; 03 设置窗体属性 按照下表的内容设置窗体的相关属性: 设置属性 …

HCIP之PPP协议(PAP认证,CHAP认证)、GRE、MGRE综合实验

实验过程 一、IP配置 [r1]interface Serial 4/0/0 [r1-Serial4/0/0]ip ad 15.1.1.1 24 [r1]interface GigabitEthernet 0/0/0 [r1-GigabitEthernet0/0/0]ip ad 192.168.1.1 24 r2]interface Serial 4/0/0 [r2-Serial4/0/0]ip ad 25.1.1.2 24 [r2]interface GigabitEthernet 0/…

Web漏洞扫描工具(AWVS、Goby)

一、背景 想针对自己项目或者小公司的Web安全做相关扫描&#xff0c;自己做漏洞进行自查工作&#xff0c;能够减少自身系统的安全风险&#xff0c;提高系统的安全性。但是没有找到一些开源性质的、扫描质量比较高的相关工具&#xff0c;使用安全公司的专业产品价格又承受不起。…

生成式人工智能之路,从马尔可夫链到生成对抗网络

人工智能&#xff08;Artificial intelligence&#xff0c;AI&#xff09;技术在过去几年中取得了显著进展&#xff0c;其中生成式AI&#xff08;Generative AI&#xff09;因其强大的内容生成能力而备受关注。生成式AI可以创建新的文本、图像、音频、视频、代码以及其他形式的…

Java中定时任务执行的三种方式

Java中定时任务执行的三种方式 1. 普通线程死循环1.1 优点1.2 缺点1.3 示例代码片段 2. 使用定时器 Timer2.1 优点2.2 缺点2.3 示例代码片段 3. 使用定时调度线程池 ScheduledExecutorService3.1 优点3.2 缺点3.3 示例代码片段 &#x1f496;The Begin&#x1f496;点点关注&a…

Vue使用FullCalendar实现日历/周历/月历

Vue使用FullCalendar实现日历/周历/月历 需求背景&#xff1a;项目上遇到新需求&#xff0c;要求实现工单以日/周/月历形式展示。而且要求不同工单根据状态显示不同颜色&#xff0c;一个工单内部&#xff0c;需要以不同颜色显示三个阶段。 效果图 日历 周历 月历 安装插件…

Spring之Spring Bean的生命周期

Spring Bean的生命周期 通过BeanDefinition获取bean的定义信息调用构造函数实例化beanBean的依赖注入处理Aware接口&#xff08;BeanNameAware、BeanFactoryAware、ApplicationContextAware&#xff09;Bean的后置处理器BeanPostProcessor-前置初始化方法&#xff08;Initiali…

Java基础(四) 内部类详解

Java 内部类详解 一. 内部类概述 内部类是嵌套在类内部进行定义的类&#xff0c;其外部的类则被称为外部类&#xff1b;按照内部类的定义位置&#xff0c;内部类可进一步划分为成员内部类、静态内部类、局部内部类和匿名内部类四种类型。内部类的出现实际上是进一步丰富了类的…

React 学习——行内样式、外部样式、动态样式

三种样式的写法 import "./index.css"; //同级目录下的样式文件 function App() {const styleCol {color: green,fontSize: 40px}// 动态样式const isBlock false;return (<div className"App">{/* 行内样式 */}<span style{{color:red,fontSiz…

FreeModbus学习——eMBPoll轮询

FreeModbus版本&#xff1a;1.6 eMBPoll在mb.c文件中 eMBPoll 函数是一个核心的 Modbus 协议栈事件处理函数&#xff0c;负责接收和发送帧&#xff0c;处理不同的事件&#xff0c;并根据需要返回错误码。 eMBErrorCode eMBPoll( void ) {static UCHAR *ucMBFrame; …

zabbix添加钉钉告警机器人使用bash和python两种脚本

zabbix添加钉钉告警机器人使用bash和python两种脚本 查看脚本目录 vi /etc/zabbix/zabbix_server.conf# 脚本存放路径 AlertScriptsPath/usr/lib/zabbix/alertscripts编写脚本&#xff08;二选一&#xff09; bash脚本 编写脚本 cd /usr/lib/zabbix/alertscripts vi zabbi…

00 RabbitMQ:前言

00 RabbitMQ&#xff1a;前言 1. 前言1.1. 举个&#x1f330;&#xff1a;快递案例1.1.1. 过程对比1.1.2. 延伸到程序中 1.2. 举个&#x1f330;&#xff1a;订单案例1.2.1. 流程1.2.2. 耦合1.2.3. 响应时间1.2.4. 并发压力1.2.5. 系统结构弹性 1.3. 总结 1. 前言 1.1. 举个&a…

机器人开源调度系统OpenTCS-6最新版本地源码运行

OpenTCS 项目使用 Gradle 而不是 Maven&#xff0c;那么需要使用 Gradle 来导入和构建项目。在 IntelliJ IDEA 中导入和运行使用 Gradle 的项目&#xff0c;可以按照以下步骤进行操作&#xff1a; 克隆 OpenTCS 源码 首先&#xff0c;克隆 OpenTCS 的源码到本地。您可以使用以…

2. 深度学习的项目流程(批量化打包数据、构建模型、训练模型、波士顿房价预测、激活函数、多层感知机)

深度学习流程 1. 深度学习基本流程1.1 流程图1.2 代码实现1.3 基本概念 2. 深度学习项目流程2.1 批量化打包数据2.2 构建模型2.3 训练模型&#xff08;1&#xff09;筹备训练&#xff08;2&#xff09;开始训练 2.4 模型推理 3. 深度学习实现波士顿房价预测3.1 数据读取、切分、…

Visio绘制的Sigmoid激活函数结构图,可导出高清图片,可修改,无水印。

Visio绘制的Sigmoid激活函数结构图,可导出高清图片&#xff0c;可修改&#xff0c;无水印。 方便用于小论文写作&#xff0c;方便用于毕业设计。 Visio版本为2021版&#xff0c;可用更高版本打开。 下载地址&#xff1a;地址 图片展示&#xff1a;

对递归的一些理解。力扣206题:翻转链表

今天在刷力扣的时候&#xff0c;在写一道翻转链表的题目的过程中&#xff0c;在尝试使用递归解决该问题的时候&#xff0c;第一版代码却每次都返回的是null&#xff0c;这个错误让我尝试去debug了一下&#xff0c;最终找出了问题&#xff0c;并且让我对递归有了一些更深的理解&…

Windows下帆软BI(finebi)单机部署移植(Tomcat)攻略

一、基础环境 操作系统&#xff1a;Windows 10 64bit 帆软BI 版本&#xff1a;V9.0/V10.0 HTTP工具&#xff1a;Tomcat 外置数据库&#xff1a;Oracle 11g 实验内容&#xff1a;将已经部署好的帆软BI从一台电脑移植到另一台电脑 二、前期准备 1、做好外置数据库移植&…