牛客网_NC198.判断是不是完全二叉树
题目描述
给定一个二叉树,确定他是否是一个完全二叉树。
完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)
数据范围:节点数满足1≤n≤100
图示
思路分析
要想把这道题做好,首先必须得知道完全二叉树的特点
- 完全二叉树的节点个数范围在:[2^ (h-1), 2^h-1]
- 完全二叉树是连续不断的
根据这两个特点来想解决办法:
利用完全二叉树范围的特点来判断(错误方法)
有一种思路:可以根据完全二叉树的节点个数来判断是不是完全二叉树,但是看似没问题,实则没办法判断;
因为如果个数达标,但是并不连续,则也不是完全二叉树
如下图:
结点个数在完全二叉树的范围之中,但是仍然不是完全二叉树;
所以基本可以判断,利用这个性质是没办法直接判断的
利用完全二叉树连续的特点来判断(正确方法)
因为它是连续的,所以我们可以利用层序遍历的特点来判断
如果说层序遍历的结果是这样的【1, 2, 3, 4, 5, NULL,NULL,NULL……】,那么他就是完全二叉树,因为在这个结果中,当出现NULL后就不会再出现数字了
但如果是这样的:【1, 2, 3, 4, 5,NULL,6, NULL,NULL,NULL……】
那就不是完全二叉树
所以思路就是:走一遍层序遍历,然后在层序遍历之间加上判断
样例代码
部分代码(只是判断是不是完全二叉树)
//判断是不是完全二叉树
bool BTComplete(BTNode* root)
{
//先分析完全二叉树的特点
//连续,层序遍历
Queue Q;
QueueInit(&Q);
if (root != NULL)
{
QueuePush(&Q, root);
}
int size = 0;
while (!QueueEmpty(&Q))
{
BTNode* front = QueueFront(&Q);
//当节点里出现NULL了,那就做一个标记
//记录这个时候已经出现过NULL了
if (!front)
{
//如果front是NULL,就做标记
size = 1;
}
//根据标记,可以知道,之前已经出现过NULL了
if (front && size == 1)
{
//之前已经出现过NULL了,但是却出现了正常数字
return false;
}
QueuePop(&Q);
if (front)
{
QueuePush(&Q, front->left);
QueuePush(&Q, front->right);
}
}
QueueDestroy(&Q);
return true;
}
从牛客网上拷贝出来的,可以直接提交的完整代码
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return bool布尔型
*/
typedef struct TreeNode* QDataType;
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
void QueueInit(Queue* pq)
{
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
void QueueDestroy(Queue* pq)
{
QNode* cur = pq->phead;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
void QueuePush(Queue* pq, QDataType x)
{
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail\n");
return;
}
newnode->data = x;
newnode->next = NULL;
if (pq->ptail == NULL)
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
void QueuePop(Queue* pq)
{
// 1、一个节点
// 2、多个节点
if (pq->phead->next == NULL)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
// 头删
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->size--;
}
QDataType QueueFront(Queue* pq)
{
return pq->phead->data;
}
QDataType QueueBack(Queue* pq)
{
return pq->ptail->data;
}
int QueueSize(Queue* pq)
{
return pq->size;
}
bool QueueEmpty(Queue* pq)
{
/*return pq->phead == NULL
&& pq->ptail == NULL;*/
return pq->size == 0;
}
bool isCompleteTree(struct TreeNode* root )
{
//先分析完全二叉树的特点
//连续,层序遍历
Queue Q;
QueueInit(&Q);
if (root != NULL)
{
QueuePush(&Q, root);
}
int size = 0;
while (!QueueEmpty(&Q))
{
struct TreeNode* front = QueueFront(&Q);
if (!front)
{
size = 1;
}
if (front && size == 1)
{
return false;
}
QueuePop(&Q);
if (front)
{
QueuePush(&Q, front->left);
QueuePush(&Q, front->right);
}
}
QueueDestroy(&Q);
return true;
}
总结
以上就是今天要讲的内容,本文简单介绍了 牛客网_NC198.判断是不是完全二叉树 的解题思路,在力扣以及牛客网中还会有很多类似的题目,今后将会持续更新,敬请关注!