首先我们要了解什么事完全二叉树。
完全二叉树:
假设一颗二叉树的深度为h,除了第h层以外,其余各层节点的个数全都达到了每层的最大值,即2^(n-1),只有第h层的结点个数小于或者等于2^(h-1),而且节点都连续集中在最左边,这就是完全二叉树,当然当第h层结点达到最大值时,叫做满二叉树,满二叉树是一种特殊的完全二叉树;
如图所示为完全二叉树:
从根结点开始遍历整棵二叉树,(所假设的节点之前为完全二叉树)
如果一个节点只有右孩子,则不是完全二叉树,
若一节点只有左孩子,就要判断其后是否还有节点,若孩子有,则不是完全二叉树,若没有则为完全二叉树
如果一个节点既有左孩子又有右孩子或者没有左右孩子,则判断他后边是否还有节点,若没有则为完全二叉树
这也是层序遍历的变形,第一种用标记的方法:
bool IsFullTree(TreeNode* root)
{
bool flag = false;
queue<TreeNode*> q;
q.push(root);
while (!q.empty())
{
TreeNode* cur = q.front();
if (!flag)
{
//当前节点有左右孩子
if (cur->left&&cur->right)
{
q.push(cur->left);
q.push(cur->right);
}
//当前节点只有左孩子,他之后的节点不能有孩子
else if (cur->left)
{
q.push(cur->left);
flag = true;
}
//当前节点只有右孩子
else if (cur->right)
{
return false;
}
//当前节点没有孩子,判断其下一个节点
else
flag = true;
}
else
{
if (cur->left || cur->right)
return false;
}
q.pop();
}
return true;
}
再看另外一种方法:剩余队列判空法
层序遍历的时候我们都是只把不为空的左右孩子送入队列中,现在我们吧层序遍历到的每个节点的左右孩子不管为空还是不为空都送入队列中,若为完全二叉树,则不断的pop(),当遇到第一个为空的结点后,队列中剩下的结点应该都为空,若海域非空的结点,则不是完全二叉树,下面看图更好的说明一下:
此图为完全二叉树及其队列:
下图则不是完全二叉树,看起队列:
由图可以看出,不是完全二叉树的,队列里边第一个空节点之后还有非空结点。
bool IsFullTree(TreeNode* root)
{
queue<TreeNode*>q;
q.push(root);
TreeNode* front = NULL;
//队列中第一个节点为空跳出
while (front = q.front())
{
q.push(front->left);
q.push(front->right);
q.pop();
}
while (!q.empty())
{
//第一个空节点之后的节点不为空,则返回
if (q.front() != NULL)
return false;
q.pop();
}
return true;
}