二叉树经典面试题4~判断一棵树是否是完全二叉树
2017-07-27 19:03
381 查看
转载:点击打开链接
二叉树经典面试题4~判断一棵树是否是完全二叉树
一.问题描述有一棵树判断该树是否是完全二叉树?
二.问题分析
1.完全二叉树的定义?
判断一棵树是否是完全二叉树,首先要知道什仫是完全二叉树?完全二叉树就是除最后一层外,每一层上的结点数均达到最大值;在最后一层上只缺少右边的若干结点。
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。
一棵二叉树至多只有最下面的两层上的结点的度数可以小于2,并且最下层上的结点都集中在该层最左边的若干位置上,则此二叉树成为完全二叉树。
2.如何判断一棵树是完全二叉树?
在了解了完全二叉树的概念之后,相信读者应该都会判定一颗树是否是完全二叉树了,根据完全二叉树的定义,我们知道完全二叉树的前h-1是满二叉树,而最后一层又是从左到右没有间隔的,如果对这棵树进行层序遍历会发生什仫情况呢?详细介绍见下。在这里我提到两种判断完全二叉树的方法:
1).标记法
设置标记flag=false,如上图所示,从根结点开始层序遍历入队列,如果队列不为空,一直循环。遇到第一个没有左孩子或者右孩子的结点,设置标记位flag=true,如果继续入队列再次遇到存在孩子的结点一定不是完全二叉树。
//设置标志位的方法
bool IsCompleteBinaryTree1()
{
bool flag=false;
queue<Node *>q;
q.push(_root);
Node *cur=q.front();
while (cur)
{
//有右孩子无左孩子
if(cur->_left == NULL && cur->_right != NULL)
return false;
//标志位为true并且当前结点存在孩子
if(flag == true && (cur->_left || cur->_right))
return false;
//如果当前结点少一个孩子
if(cur->_left == NULL || cur->_right == NULL)
flag=true;
if(cur->_left)
q.push(cur->_left);
if(cur->_right)
q.push(cur->_right);
q.pop();
if(!q.empty())
cur=q.front();
else
cur=NULL;
}
return true;
}
2).剩余队列判空法
突然发现使用上述标记法要考虑的情况很多,不太方便,于是又提出了另一种方法,就是剩余队列判空法
这个方法同样的用到了队列这种辅助结构,那仫如何只通过队列这个结构来判断一棵树是否是完全二叉树呢?试想一下,如果我们把一棵树的所有结点,包括叶子结点的左右空孩子都通过层序遍历入队列会发生什仫情况?详细的分析见下图:
[cpp]
view plain
copy
print?
//利用辅助队列的办法
bool IsCompleteBinaryTree2()
{
queue<Node *>q;
q.push(_root);
Node *cur=q.front();
//按照层序遍历的办法入队列直到遇到第一个NULL停止
while (cur)
{
q.push(cur->_left);
q.push(cur->_right);
q.pop();
cur=q.front();
}
//如果队列中全为NULL则是完全二叉树,否则不是
while(!q.empty())
{
if(q.front())
return false;
q.pop();
}
return true;
}
三.完整的代码实现
[cpp]
view plain
copy
print?
template<class T>
struct BinaryTreeNode
{
T _data;
BinaryTreeNode<T> *_left;
BinaryTreeNode<T> *_right;
BinaryTreeNode(const T& data)
:_data(data)
,_left(NULL)
,_right(NULL)
{}
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(const T*a,size_t size,const T& invalid)
{
size_t index=0;
_root=_CreatTree(a,size,index,invalid);
}
//设置标志位的方法
bool IsCompleteBinaryTree1()
{
bool flag=false;
queue<Node *>q;
q.push(_root);
Node *cur=q.front();
while (cur)
{
//有右孩子无左孩子
if(cur->_left == NULL && cur->_right != NULL)
return false;
//标志位为true并且当前结点存在孩子
if(flag == true && (cur->_left || cur->_right))
return false;
//如果当前结点少一个孩子
if(cur->_left == NULL || cur->_right == NULL)
flag=true;
if(cur->_left)
q.push(cur->_left);
if(cur->_right)
q.push(cur->_right);
q.pop();
if(!q.empty())
cur=q.front();
else
cur=NULL;
}
return true;
}
//利用辅助队列的办法
bool IsCompleteBinaryTree2()
{
queue<Node *>q;
q.push(_root);
Node *cur=q.front();
//按照层序遍历的办法入队列直到遇到第一个NULL停止
while (cur)
{
q.push(cur->_left);
q.push(cur->_right);
q.pop();
cur=q.front();
}
//如果队列中全为NULL则是完全二叉树,否则不是
while(!q.empty())
{
if(q.front())
return false;
q.pop();
}
return true;
}
protected:
Node* _CreatTree(const T*a,size_t size,size_t& index,const T& invalid)
{
assert(a);
Node *root=NULL;
if(index < size && a[index] != invalid)
{
root=new Node(a[index]);
root->_left=_CreatTree(a,size,++index,invalid);
root->_right=_CreatTree(a,size,++index,invalid);
}
return root;
}
protected:
Node *_root;
};
void testIsCompleteTree()
{
//int array[]={0,1,3,'#','#','#',2,4,'#','#',5}; //false
//int array[]={0,1,3,'#','#',4,'#','#',2,5,'#','#','#'}; //true
//int array[]={0,1,3,'#','#',4,'#','#',2}; //true
int array[]={0,1,3,'#','#','#',2};
size_t size=sizeof(array)/sizeof(array[0]);
BinaryTree<int> bt(array,size,'#');
bool ret=bt.IsCompleteBinaryTree2();
if(ret == true)
cout<<"是完全二叉树"<<endl;
else
cout<<"不是完全二叉树"<<endl;
}
相关文章推荐
- 二叉树经典面试题4~判断一棵树是否是完全二叉树
- 二叉树镜像(递归和非递归)+ 判断一棵二叉树是否是平衡二叉树+ 判断一棵树是否为完全二叉树
- 二叉树系列问题——判断一棵树是否为完全二叉树
- 判断一棵树是否是完全二叉树和求二叉树中两个节点的最近公共祖先——题集(十三)
- 二叉树面试题之判断一棵树是否为另一棵树的子树
- 二叉树--判断一棵树是否是完全二叉树
- 二叉树面试题-镜像与判断是否为完全二叉树
- 二叉树面试题—前,中,后序(非递归),判断是否为完全二叉树
- 数据结构面试题/判断一棵树是否是完全二叉树
- 刷题之二叉树----判断一棵树是否为完全二叉树
- 【二叉树】层次遍历二叉树以及判断一棵树是否是完全二叉树
- 【面试题】判断一棵二叉树是否是完全二叉树
- 二叉树问题---判断一棵树是否为完全二叉树
- 二叉树面试题:判断树是否为完全二叉树和求二叉树的镜像
- 设计一个算法,判断一个二叉树是否为完全二叉树
- 判断二叉树是否是完全二叉树
- 判断二叉树是否为完全二叉树的实例
- C/C++经典面试题之判断链表是否有环
- 判断一棵二叉树是否为完全二叉树
- 判断一棵树是否为完全二叉树