110.【C语言】数据结构之判断是否为完全二叉树

目录

1.知识回顾

2.分析

完全二叉树队列示意图

非完全二叉树队列示意图

区别

3.代码

执行过程

完整代码

运行结果


1.知识回顾

完全二叉树和非完全二叉树参见100.【C语言】数据结构之二叉树的基本知识文章

2.分析

使用层序遍历(队列),核心思想参见109.【C语言】数据结构之二叉树层序遍历文章

这里对比完全二叉树和非完全二叉树在层序遍历中的区别

注意:和以往的层序遍历有所不同,空节点也要push(push它的地址NULL)

完全二叉树队列示意图

非完全二叉树队列示意图

区别

当两个队列的队头为NULL时,观察两个队列之间的区别

完全二叉树:元素全为空

非完全二叉树:有非空元素

可以此来判断是否为完全二叉树

3.代码

执行过程

初始化队列-->非空树,将根节点的地址入队-->层序遍历+出栈+入栈-->对队头的值判断(为NULL则一直出队,遇到非空则销毁队列+返回false)

层序遍历+出栈+入栈

根节点出栈,出栈前需要保留根节点的地址,以便于左右节点入栈(front->left和front->right,不是root->left和root->right)

大概的结构

cpp 复制代码
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		QueuePush(&q,front->left);
		QueuePush(&q,front->right);

疑问1:不是对根节点的左右节点入栈吗?为什么不写成root->left和root->right呢?

root一直是整个二叉树根节点的地址,导致root->left和root->right的值一直没有变化,导致死循环

如果写成front->left和front->right,每次循环时,front的值会改变(依据队头的值进行调整)

cs 复制代码
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL) 
			break;

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

最终当队头为NULL时,退出循环

疑问2:第一个while的部分能写成下面这两种吗?

cpp 复制代码
BTNode* front = QueueFront(&q);
while (1)
{
	front = QueueFront(&q);
	QueuePop(&q); 
	if (front == NULL)
	{
		break;
	}
	QueuePush(&q, front->left);
	QueuePush(&q, front->right);
}
cpp 复制代码
	while (QueueFront(&q))
	{
		BTNode*  front = QueueFront(&q);
		QueuePop(&q); 
		if (front == NULL)
		{
			break;
		}
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}

两种写法均可以,while循环退出的唯一出口在if (front==NULL),由于NULL也入队,因此不存在队列为空的情况

完整代码

cpp 复制代码
bool TreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front == NULL) 
			break;

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

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}
	QueueDestroy(&q);
	return true;	
}

注意返回前养成好习惯,需要销毁队列

main.c写入

cpp 复制代码
int main()
{
    BTNode* root = CreateTree();
    printf("TreeComplete:%d", TreeComplete(root));
    return 0;
}

备注:创建的二叉树的结构为

运行结果

相关推荐
爱笑的k117 小时前
nano-vllm 源码剖析:千行 Python 手写离线推理引擎的调度、显存与并行时序
开发语言·python·vllm
X1A0RAN8 小时前
PPT 图片批量处理教程:导出全部幻灯片 · 提取全部素材
开发语言·javascript·powerpoint
熊猫钓鱼>_>10 小时前
普通用户视角的端侧智能体验手记【鸿蒙心迹】
开发语言·人工智能·华为·智能手机·性能优化·ai编程·harmonyos
瑞雪兆丰年兮10 小时前
JavaWeb-day13-SpringBootWeb事务管理&AOP
java·开发语言·springboot·javaweb·事务·web·aop
布莱克60512 小时前
Swift 常量详解:从 let 到编译期优化
服务器·开发语言·ssh·swift·常量·let
布莱克60512 小时前
Swift 可选类型(Optionals)详解:从原理到实战
开发语言·安全·ssh·swift·optional·可选类型
Severus_black13 小时前
【C++初阶】Stack、Queue算法题大练兵!
c语言·c++·算法·stl
瑞雪兆丰年兮14 小时前
JavaWeb-day14-SpringBootWeb原理篇
java·开发语言·spring boot·spring·bean·mybatis·javaweb
唐青枫15 小时前
C 语言 strcpy() 用法详解与实战 Demo
c语言
SomeOtherTime15 小时前
Rust生命周期介绍(AI回答)
开发语言·后端·rust