当前位置: 首页 > article >正文

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

目录

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

手搓一个完全二叉树

代码实现 


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

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


手搓一个完全二叉树

// 数据类型
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.kler.cn/a/405070.html

相关文章:

  • python oa服务器巡检报告脚本的重构和修改(适应数盾OTP)有空再去改
  • 如何删除Kafka中的数据以及删除topic
  • 循环输出1~100之间的每个数
  • 国产linux系统(银河麒麟,统信uos)使用 PageOffice 动态生成word文件
  • 记录一下在原有的接口中增加文件上传☞@RequestPart
  • 3-22 ElementPlus:表单
  • 数学建模学习(137):使用Python进行频数分析
  • c#基本数据类型占用字节长度/取值范围/对应.net类型
  • 【机器学习】聚类算法原理详解
  • python: generator model using sql server 2019
  • linux命令之netstat用法
  • MySQL 的 INSERT(插入数据)详解
  • 前端八股自学笔记分享—页面布局(二)
  • ETSI TS 102 226 V9.0.0 远程管理规范笔记
  • 利用Python编写简单登录系统
  • vim 使用技巧
  • 【ubuntu】ubuntu 22.04 切 gcc/g++ 版本
  • uniapp 城市选择插件
  • 人形机器人赛道资本之争:“南”[智元机器人],“北”[银河通用]
  • C语言:数组
  • Java集合HashMap——针对实习面试
  • 半导体工艺与制造篇3 离子注入
  • Vue2创建原神官网界面(Vue2+html+css+jquery),速通vue项目(抽象但是实用)
  • 2411rust,正与整128
  • 库卡机器人日常维护
  • BERT的中文问答系统32