目录
二叉树的层序遍历实现代码:(1条消息) 【C语言】二叉树的层序遍历_吃饭爱喝水的博客-优快云博客
要判断一颗树是否是完全二叉树,我们得首先了解一下完全二叉树的定义吧!
完全二叉树的定义
这就是完全二叉树的定义。
用我自己的理解来说就是:一颗二叉树,它的每一层的节点都必须是全满的,不能有空。且同时,最后一层的节点也必须从左至右是连续存在的。那么,这颗树就是一颗完全二叉树。(满二叉树是特殊的完全二叉树)
如何代码实现判断一棵二叉树是完全二叉树
根据完全二叉树的定义可知,它是从第一层开始,到它的N-1层时,每一层的节点都是满的。最后一层,也就是第N层的节点也是从左至右连续存在节点。
到这里,看看这是不是和二叉树的层序遍历有点相似呢?
没错的,就是利用层序遍历来判断其是否是完全二叉树!
二叉树的层序遍历实现代码:(1条消息) 【C语言】二叉树的层序遍历_吃饭爱喝水的博客-优快云博客
我们可以根据二叉树层序遍历二叉树的结果来看。
首先,先假设遍历到空节点为 *
那么,对下面这颗二叉树(非完全二叉树)的层序遍历结果就是:1 2 4 3 * 5 6 * * * * * ....
那么,对下面这颗二叉树呢?(完全二叉树)
层序遍历结果为:1 2 4 3 7 5 6 * * * * * * * .....
具体思路:
这里我们再把非完全二叉树的遍历结果和完全二叉树的遍历结果拿下来对比一下:
非完全:1 2 4 3 * 5 6 * * * * * ....
完全:1 2 4 3 7 5 6 * * * * * * * .....
我们可以看到,完全二叉树只要出现了空节点,那么后面全部都是空节点。
而非完全二叉树呢?出现二叉树节点之后,后面仍然会出现非空节点。
那么,我们就可以根据我们发现的这个特征来实现代码了!
其重点就是:当遍历层序遍历二叉树的结果时,只要出现了空节点,这时,我们只需要再判断其后面是不是全为空。只要是在空节点后面的队列中出现了一个非空节点的话,那么这棵二叉树就不是一颗完全二叉树。
层序遍历实现核心代码:
void TreeLevelOrder(root) {
Queue pq;
QueueInit(&pq);//创建一个队列,利用其先进先出的特性并结合二叉树实现层序遍历
if (root) {//首先,判断二叉树是否是空树。不是空树,就将根节点入队列
QueuePush(&pq, root);
}
while (!QueueEmpty(&pq)) {//判断栈是否为空队列,不为空栈的话就可以进入程序中循环
BTNode* front = QueueFront(&pq);//先将根节点的地址拿出来
QueuePop(&pq);//将根节点弹出队列(注意:二叉树并没有被销毁)
printf("%d ", front->data);
if (front->left) {//判断根节点的左子树是否存在
QueuePush(&pq, front->left);//如果存在则将其入队列
}
if (front->right) {//判断根节点的右子树是否存在
QueuePush(&pq, front->right);//如果存在,则将其入队列
}
}
printf("\n");
QueueDestory(&pq);//队列这时已经空了,后面也不需要使用了,所以将其置空。
}
————————————————
版权声明:本文为优快云博主「吃饭爱喝水」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/wzx0806/article/details/132000652
其层序遍历代码的实现主要是利用了队列的先进先出特性来实现的。我们接下来也主要是利用其特性来判断的。
主要是因为我们在遍历的时候一旦找到空的时候,需要跳出循环来判断下空节点之后的队列是不是空队列
假如这时,这个队列是个空队列的话,那么这个二叉树就是一颗完全二叉树。
当它这时,队列不为一个非空队列的话,我们就需要遍历整个队列,看其是否有一个二叉树节点不为空。
判断是否为完全二叉树的核心代码:
bool isCompleteBinaryTree(root) {
Queue pq;
QueueInit(&pq);//创建一个队列,利用其先进先出的特性并结合二叉树实现层序遍历
if (root){//首先,判断二叉树是否是空树。不是空树,就将根节点入队列
QueuePush(&pq, root);
}
while (!QueueEmpty(&pq)) {//判断是否为空队列,不是的话就可以进入程序中循环
BTNode* front = QueueFront(&pq);//先将根节点的地址拿出来
QueuePop(&pq);//将根节点弹出队列(注意:二叉树并没有被销毁)
if (front){//当节点不为空,将其左右孩子入队列
QueuePush(&pq, front->left);
QueuePush(&pq, front->right);
}
else {//一旦发现空节点,直接跳出循环
break;
}
}
if(!QueueEmpty(&pq)) {//接着判断跳出循环后剩下的队列是否为空,不为空则进入,否则返回true
BTNode* front = QueueFront(&pq);
QueuePop(&pq);
if(front){
QueueDestory(&pq);//***注意,这里也需要销毁,否则有内存溢出的潜在风险。
return false;
}
}
QueueDestory(&pq);
return true;
}
图解讲解:
就比如以上这张图:当层序遍历访问到空节点时,剩余的队列中的元素为: * 5 6
这时,我们发现空节点之后的队列不全为空,这时,就可判定它就不是一个完全二叉树了。
以上这张图,当其访问到空节点跳出循环之后,空节点之后的队列为: * * * * * *....
因此,紧接着的循环判断空节点之后的队列是全为空的,所以可判定其为一颗完全二叉树了。