数据结构 ——— 判断一棵树是否是完全二叉树

news2024/11/22 20:37:42

目录

满二叉树和完全二叉树示意图

手搓一个完全二叉树

代码实现 


满二叉树和完全二叉树示意图

注意区分满二叉树和完全二叉树
满二叉树的每一层都是满的,也就是除了叶子节点,其他节点都有左右节点
完全二叉树的最后一层不一定是满的,但是从左到右是连续的


手搓一个完全二叉树

// 数据类型
typedef int BTDataType;

// 二叉树节点的结构
typedef struct BinaryTreeNode
{
	BTDataType data; //每个节点的数据

	struct BinaryTreeNode* left; //指向左子树的指针

	struct BinaryTreeNode* right; //指向右子树的指针
}BTNode;

// 申请新节点
BTNode* BuyNode(BTDataType x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));

	// 判断是否申请成功
	if (newnode == NULL)
	{
		perror("malloc fail");
		return NULL;
	}

	// 初始化
	newnode->data = x;
	newnode->left = NULL;
	newnode->right = NULL;

	return newnode;
}

BTNode* CreatBinaryTree1()
{
	BTNode* n1 = BuyNode(1);
	assert(n1);
	BTNode* n2 = BuyNode(2);
	assert(n2);
	BTNode* n3 = BuyNode(3);
	assert(n3);
	BTNode* n4 = BuyNode(4);
	assert(n4);
	BTNode* n5 = BuyNode(5);
	assert(n5);
	BTNode* n6 = BuyNode(6);
	assert(n6);
	
	n1->left = n2;
	n1->right = n3;
	n2->left = n4;
	n2->right = n5;
	n3->left = n6;

	return n1;
}

代码实现

实现思路:

通过层序遍历来判断是否是完全二叉树
数据结构 ——— 层序遍历链式二叉树_层序遍历输出二叉树-CSDN博客
同样是需要一个队列来实现,从根节点开始,只要不是空就出队列,出队列前带入左右子树
当遇到空就截至,并且遍历队列中剩下的元素是否都为空
都为空的话那就是完全二叉树,否则就不是

实现前要先构建一个简易队列以及队列的基本函数: 

// 数据类型
typedef BTNode* QDataType;
 
// 链式队列每个节点的结构
typedef struct QueueNode
{
	struct QueueNode* next; //指向下一个节点的指针
 
	QDataType data; //当前节点的数据
}QNode;
 
// 链式队列的结构
typedef struct Queue
{
	QNode* phead; //指向队头节点的指针
 
	QNode* ptail; //指向队尾节点的指针
 
	int size; //队列的总数据个数
}Queue;
 
// 初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
 
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
 
// 数据入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
 
	// 申请新节点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
 
	// 判断是否申请成功
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
 
	// 初始化新节点
	newnode->data = x;
	newnode->next = NULL;
 
	if (pq->phead == NULL) //当队列中没有数据的情况
	{
		// 双重判断,更加保险
		assert(pq->ptail == NULL);
 
		// 头尾都指向新节点即可
		pq->phead = newnode;
		pq->ptail = newnode;
	}
	else //当队列已有数据的情况
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
 
	pq->size++;
}
 
// 数据出队列
void QueuePop(Queue* pq)
{
	assert(pq);
 
	// 当队列中没有数据的情况
	if (pq->phead == NULL)
	{
		perror(pq->phead);
		return;
	}
 
	if (pq->phead->next == NULL) //当队列中只有一个数据的情况
	{
		free(pq->phead);
		
		pq->phead = NULL;
		pq->ptail = NULL;
	}
	else //当队列中有多个数据的情况
	{
		QNode* next = pq->phead->next;
		free(pq->phead);
		pq->phead = next;
	}
 
	pq->size--;
}
 
// 访问队头数据
QDataType QueueFront(Queue* pq)
{
	assert(pq);
 
	// 当队列中没有数据的情况
	if (pq->phead == NULL)
	{
		perror(pq->phead);
		return -1;
	}
 
	return pq->phead->data;
}
 
// 判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
 
	return (pq->phead == NULL) && (pq->ptail == NULL);
}
 
// 释放队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
 
	QNode* cur = pq->phead;
 
	while (cur != NULL)
	{
		QNode* next = cur->next;
 
		free(cur);
 
		cur = next;
	}
 
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

代码实现:

bool BTreeComplete(BTNode* root)
{
	// 定义队列
	Queue q;
	// 初始化队列
	QueueInit(&q);

	// 先将二叉树的根节点的指针入队列
	if (root != NULL)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		// 访问队头数据
		BTNode* front = QueueFront(&q);

		// 判断是否为空
		if (front == NULL)
			break;

		// 队头数据出队列
		QueuePop(&q);

		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}

	// 检查有没有非空节点
	while (!QueueEmpty(&q))
	{
		// 访问队头数据
		BTNode* front = QueueFront(&q);

		if (front != NULL)
		{
			// 返回前先销毁队列
			QueueDestroy(&q);

			return false;
		}

		QueuePop(&q);
	}

	QueueDestroy(&q);
	
	return true;
}

代码验证:

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

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

相关文章

Vue_Router权限控制:不同角色显示不同路由

写在前面 在Vue中,Router是一个官方提供的用于处理应用程序路由的插件。它允许我们创建单页应用程序(SPA),其中不同的页面和组件可以通过URL进行导航和展示。使我们可以轻松地创SPA,并实现可复用和可组合的组件…

java多线程并发执行方法或者调用接口

在开发过程中有时需要检查某个接口或者某个方法是否存在并发安全问题,我们会用到jmeter 、AB 等压测工具辅助我们完成代码测试,虽然这些工具功能很强大,也很好用,但是在开发过程中来使用还是不如直接执行Test 或者main 方法来的方…

Python小游戏28——水果忍者

首先,你需要安装Pygame库。如果你还没有安装,可以使用以下命令进行安装: 【bash】 pip install pygame 《水果忍者》游戏代码: 【python】 import pygame import random import sys # 初始化Pygame pygame.init() # 设置屏幕尺寸 …

测评部署和管理 WordPress 最方便的面板

新版宝塔面板快速搭建WordPress新手教程 - 倚栏听风-Morii - 博客园 初学者使用1Panel面板快速搭建WordPress网站 - 倚栏听风-Morii - 博客园 可以看到,无论是宝塔还是1Panel,部署和管理WordPress都有些繁琐,而且还需要额外去配置Nginx和M…

OpenAI Adjusts Strategy as ‘GPT’ AI Progress Slow

注:本文为两篇关于当前大模型方向讨论的文章。 OpenAI 大改下代大模型方向,scaling law 撞墙?AI 社区炸锅了 机器之心 2024 年 11 月 11 日 11:57 北京 机器之心报道 编辑:Panda、泽南 大模型的 scaling law 到头了&#xff1f…

Java开发者必备:23种设计模式全面解析

文章目录 一、创建型模式1、工厂模式简单工厂工厂方法 2、抽象工厂模式3、原型模式4、建造者模式5、单例模式 二、结构型模式1、适配器模式2、桥接模式3、组合模式4、装饰模式5、外观模式6、享元模式7、代理模式 三、行为型模式1、解释器模式2、模板方法模式3、策略模式4、观察…

LeetCode:1008. 前序遍历构造二叉搜索树

目录 题目描述: 代码: 第一种: 第二种: 第三种:分治法 题目描述: 给定一个整数数组,它表示BST(即 二叉搜索树 )的 先序遍历 ,构造树并返回其根。 保证 对于给定的测试用例,总是有可能找到具有给定需求的二叉搜索树。 二叉搜索树 是一棵…

STM32F103 GPIO和串口实战

本节我们将会对STM32F103的硬件资源GPIO和串口进行介绍。 一、GPIO 1.1 电路原理图 LED电路原理图如下图所示: 其中: LED1连接到PA8引脚,低电平点亮;LED2连接到PD2引脚,低电平点亮; 1.2 GPIO引脚介绍 STM32…

Statsmodels之OLS回归

目录 Statsmodels基本介绍OLS 回归实战实战1:实战2: Statsmodels基本介绍 Statsmodels 是 Python 中一个强大的统计分析包,包含了回归分析、时间序列分析、假设检验等等的功能。Statsmodels 在计量的简便性上是远远不及 Stata 等软件的&…

在 macOS 和 Linux 中,波浪号 `~`的区别

文章目录 1、在 macOS 和 Linux 中,波浪号 ~macOS示例 Linux示例 区别总结其他注意事项示例macOSLinux 结论 2、root 用户的主目录通常是 /root解释示例切换用户使用 su 命令使用 sudo 命令 验证当前用户总结 1、在 macOS 和 Linux 中,波浪号 ~ 在 macO…

人工智能之机器学习5-回归算法2【培训机构学习笔记】

培训班ppt内容: 个人精进总结: 可解释方差 定义 可解释方差的回归评分函数是一种用于评估回归模型性能的指标,以下从其定义、计算公式、取值范围及意义、应用场景等方面进行详细介绍: 可解释方差(Explained Varian…

vue2中引入cesium全步骤

1.npm 下载cesium建议指定版本下载,最新版本有兼容性问题 npm install cesium1.95.0 2.在node_models中找到cesium将此文件下的Cesium文件复制出来放在项目的静态资源public中或者static中,获取去github上去下载zip包放在本地也可以 3.在index.html中引…

数据结构(顺序栈——c语言实现)

栈的基本概念: 栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈” 特点:先进后出(FI…

基于Windows系统用C++做一个点名工具

目录 一、前言 二、主要技术点 三、准备工作 四、主界面 1.绘制背景图 2、实现读取花名册功能 3.实现遍历花名册功能 4.实现储存功能 4.1创建数据库 4.2存储数据到数据库表 4.3读取数据库表数据 一、前言 人总是喜欢回忆过去,突然回忆起…

前端监控之sourcemap精准定位和还原错误源码

一、概述 在前端开发中,监控和错误追踪是确保应用稳定性和用户体验的重要环节。 随着前端应用的复杂性增加,JavaScript错误监控变得尤为重要。在生产环境中,为了优化加载速度和性能,前端代码通常会被压缩和混淆。这虽然提升了性…

算法编程题-排序

算法编程题-排序 比较型排序算法冒泡排序选择排序插入排序希尔排序堆排序快速排序归并排序 非比较型排序算法计数排序基数排序 本文将对七中经典比较型排序算法进行介绍,并且给出golang语言的实现,还包括基数排序、计数排序等非比较型的算法的介绍和实现…

Jenkins修改LOGO

重启看的LOGO和登录页面左上角的LOGO 进入LOGO存在的目录 [roottest-server01 svgs]# pwd /opt/jenkins_data/war/images/svgs [roottest-server01 svgs]# ll logo.svg -rw-r--r-- 1 jenkins jenkins 29819 Oct 21 10:58 logo.svg #jenkins_data目录是我挂载到了/opt目录&…

【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段

文章目录 一、MyBatis-Plus简介二、快速入门1、环境准备2、将mybatis项目改造成mybatis-plus项目(1)引入MybatisPlus依赖,代替MyBatis依赖(2)配置Mapper包扫描路径(3)定义Mapper接口并继承BaseM…

云讷科技Kerloud无人飞车专利发布

云讷科技Kerloud无人飞车获得了“一种室内外两用的四旋翼无人飞车”的实用新型专利证书,作为科教社区第一款四旋翼飞车,这项技术结合了无人机和无人车的优势,提供了一种能够在多种环境下使用的多功能飞行器。 这项设计的优势如下&#xff…

Applied Intelligence投稿

一、关于手稿格式: 1、该期刊是一个二区的,模板使用Springer nature格式, 期刊投稿要求,详细期刊投稿指南,大部分按Soringernature模板即可,图片表格声明参考文献命名要求需注意。 2、参考文献&#xff…