判断一棵二叉树是否为完全二叉树
2016-07-16 20:46
543 查看
1.完全二叉树的特点(来自专业定义)
看到上面完全二叉树的特点,我可以将其特点按照自己的理解归纳为以下几点:
(1):若二叉树最下面一层有节点出现,那么这个节点一定是是从左到右依次排列,若只有一个孩子,那么这个孩子一定是左孩子而不是右孩子(特殊情况,空树和只有根节点的树都是完全二叉树)。
(2)要么最后一层全为叶子节点,否则以它为根节点的孩子一定是从左依次排列的)。
2.解决这个问题的办法(全部采用广度优先遍历的方法进行遍历,并使用队列这个结构操作数据):
只要当前节点有一个孩子不为空,那么就将它的左右孩子都压入队列,出队列第一次遇到NULL节点时,做一个标记,直到队列为空后面都再无非空节点出现,那么它就一定是完全二叉树;反之若第一次出现NULL节点后再出现非空节点,那么它一定就不满足完全二叉树的定义。
3.代码实现
bool _IsCompleteTree(Node* root)
{
if (root == NULL)
{
return true;
}
if (root->_left == NULL&&root->_right == NULL)
{
return true;
}
queue<Node*> q;
bool flag = false;
q.push(root);
while (!q.empty())
{
Node* Front = q.front();
q.pop();
if (Front != NULL && (Front->_left || Front->_right))
{
q.push(Front->_left);
q.push(Front->_right);
}
if (Front == NULL)
{
flag = true;
}
else
{
flag = false;
}
}
if (flag == false)
{
return false;
}
else
{
return true;
}
}
(在这会出现bug,具体的问题出现紧跟着提出)
第一次出现NULL节点后,将flag置为true,后面遇到一个非空节点再将flag置为false,此时队列不为空,继续出队列,遇到NULL节点将flag置为true,此时队列为空,出循环,很明显,这个时候得到的结果就是错误的。
所以为了解决这种情况的误判,我们必须做以标记,在第一次出现NULL节点时并且后面紧跟着有非空节点出现时,直接返回,没有再进行判断的必要了。修改后代码如下:
bool _IsCompleteTree(Node* root)
{
if (root == NULL)
{
return true;
}
if (root->_left == NULL&&root->_right == NULL)
{
return true;
}
queue<Node*> q;
bool flag = false;
int count = 0;
q.push(root);
while (!q.empty())
{
Node* Front = q.front();
q.pop();
if (Front != NULL && (Front->_left||Front->_right))
{
q.push(Front->_left);
q.push(Front->_right);
}
if (Front== NULL)
{
flag = true;
count++;
}
else
{
if (count == 1)
{
flag = false;
return flag;
}
else
{
flag = false;
}
}
}
if (flag == false)
{
return false;
}
else
{
return true;
}
}
int array[] = { 1, 2, 3, '#', '#', 4, '#','#',5,6,'#','#',7,'#',8 };//无左孩子,有右孩子
int array[] = { 1, 2, 3, 8, '#', '#', '#', 4, '#', '#', 5, 6, '#', '#', 7 };//最下面一层有一个孩子,且是左孩子
array[] = { 1, 2, 3, '#', 9, 4, '#', '#', 5, 6, '#', '#', 7, '#', '#' };//最下面一层有一个孩子,且是右孩子
int array[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6, '#', '#', 7, '#', '#' };//最下面一层全部是叶子节点
int array[] = { 1, 2, 3, 8, '#', '#','#', 4,9, '#', '#','#', 5, 6, '#', '#', 7 };//上迎面解释的这种情况
int array[] = { 1 };//只有一个根节点
int array[] = { NULL};//空树
看到上面完全二叉树的特点,我可以将其特点按照自己的理解归纳为以下几点:
(1):若二叉树最下面一层有节点出现,那么这个节点一定是是从左到右依次排列,若只有一个孩子,那么这个孩子一定是左孩子而不是右孩子(特殊情况,空树和只有根节点的树都是完全二叉树)。
(2)要么最后一层全为叶子节点,否则以它为根节点的孩子一定是从左依次排列的)。
2.解决这个问题的办法(全部采用广度优先遍历的方法进行遍历,并使用队列这个结构操作数据):
只要当前节点有一个孩子不为空,那么就将它的左右孩子都压入队列,出队列第一次遇到NULL节点时,做一个标记,直到队列为空后面都再无非空节点出现,那么它就一定是完全二叉树;反之若第一次出现NULL节点后再出现非空节点,那么它一定就不满足完全二叉树的定义。
3.代码实现
bool _IsCompleteTree(Node* root)
{
if (root == NULL)
{
return true;
}
if (root->_left == NULL&&root->_right == NULL)
{
return true;
}
queue<Node*> q;
bool flag = false;
q.push(root);
while (!q.empty())
{
Node* Front = q.front();
q.pop();
if (Front != NULL && (Front->_left || Front->_right))
{
q.push(Front->_left);
q.push(Front->_right);
}
if (Front == NULL)
{
flag = true;
}
else
{
flag = false;
}
}
if (flag == false)
{
return false;
}
else
{
return true;
}
}
(在这会出现bug,具体的问题出现紧跟着提出)
<strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="font-size:18px;">这样写,会有一种情况出现误判,解释如下:</span></strong>
第一次出现NULL节点后,将flag置为true,后面遇到一个非空节点再将flag置为false,此时队列不为空,继续出队列,遇到NULL节点将flag置为true,此时队列为空,出循环,很明显,这个时候得到的结果就是错误的。
所以为了解决这种情况的误判,我们必须做以标记,在第一次出现NULL节点时并且后面紧跟着有非空节点出现时,直接返回,没有再进行判断的必要了。修改后代码如下:
bool _IsCompleteTree(Node* root)
{
if (root == NULL)
{
return true;
}
if (root->_left == NULL&&root->_right == NULL)
{
return true;
}
queue<Node*> q;
bool flag = false;
int count = 0;
q.push(root);
while (!q.empty())
{
Node* Front = q.front();
q.pop();
if (Front != NULL && (Front->_left||Front->_right))
{
q.push(Front->_left);
q.push(Front->_right);
}
if (Front== NULL)
{
flag = true;
count++;
}
else
{
if (count == 1)
{
flag = false;
return flag;
}
else
{
flag = false;
}
}
}
if (flag == false)
{
return false;
}
else
{
return true;
}
}
<strong style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><span style="font-size:18px;">测试用例可以多给以下几组:</span></strong>
int array[] = { 1, 2, 3, '#', '#', 4, '#','#',5,6,'#','#',7,'#',8 };//无左孩子,有右孩子
int array[] = { 1, 2, 3, 8, '#', '#', '#', 4, '#', '#', 5, 6, '#', '#', 7 };//最下面一层有一个孩子,且是左孩子
array[] = { 1, 2, 3, '#', 9, 4, '#', '#', 5, 6, '#', '#', 7, '#', '#' };//最下面一层有一个孩子,且是右孩子
int array[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6, '#', '#', 7, '#', '#' };//最下面一层全部是叶子节点
int array[] = { 1, 2, 3, 8, '#', '#','#', 4,9, '#', '#','#', 5, 6, '#', '#', 7 };//上迎面解释的这种情况
int array[] = { 1 };//只有一个根节点
int array[] = { NULL};//空树
相关文章推荐
- [C-C++]控制台用定时器
- iPhone的home键进果汁了,按起来粘粘的感觉
- 修改Eclipse neon的project explorer 下的项目名称字体设置
- 自动化运维工具Ansible详细部署
- [置顶] 求一元二次方程的解:
- MySql简单入门一
- python字符操作函数总结
- Android getColor方法提示过时
- 神奇的 echo 命令
- mongodb聚合
- windows环境下如何安装memcached教程
- Using file redirection
- java的继承和多态
- Linux进程监控工具:Supervisor
- 如何修改Matlab默认启动目录?
- POJ1625 Censored!
- MySQL基于gtid特性与xtrabackup的数据恢复
- OpenGL---三维变换
- linux上安装nginx
- [Python]安装Beautiful Soup