判断是否是完全二叉树
二叉树按二叉链表形式存储,试编写一个判别给定二叉树是否是完全二叉树的算法
算法思想
根据完全二叉树的定义,具有n个节点的完全二叉树与满二叉树中编号从1~n的节点一一对应。
采用层次遍历算法,将所有节点加入队列(包括空节点),遇到空节点时,查看其后是否有非空节点。若有,则二叉树不是完全二叉树
// 判断给定二叉树是否为完全二叉树
bool IsComplete(BTNode T)
{
BTNode* cur;
QueInit(Q);
if (!T)
{
// 空树为满二叉树
return true;
}
EnQueue(Q, T);
while (!IsEmpty(Q))
{
DeQueue(Q, cur);
if (cur)
{
// 节点非空,将其左右子树入队列
EnQueue(Q, cur->left);
EnQueue(Q, cur->right);
}
else
{
// 节点非空,检查其后是否有非空节点
while (!IsEmpty(Q))
{
DeQueue(Q, cur);
if (cur)
// 节点非空,则二叉树为非完全二叉树
return false;
}
}
}
return true;
}
完全二叉树的定义:
如果一棵二叉树的所有层都被完全填满,除了最后一层(叶子层),并且最后一层的所有节点都尽可能地靠左,那么它就是完全二叉树。
- 初始化
如果二叉树为NULL,直接返回true,空树也被认为是完全二叉树
初始化一个队列,用于遍历二叉树,并将根节点T入队 - 层次遍历二叉树
队列不为空时:每次从队列中取出一个节点cur
如果当前节点cur不为空
将其左右子树分别入队
如果当前节点cur为空
进入检查模式,验证其后是否存在非空节点
如果在此之后存在非空节点,则该二叉树不是完全二叉树,返回false - 结束条件
如果遍历到队列末尾,且未发现空节点之后还有非空节点的情况,则该二叉树为完全二叉树,返回true
判断是否是满二叉树
判断一棵树是否是满二叉树
算法思想
满二叉树的定义是:
一棵二叉树中,每个节点要么没有子节点,要么有两个子节点,并且所有叶子节点都在同一层。
- 递归法: 检查树是否满足:
所有节点要么有 0 个子节点,要么有 2 个子节点
左右子树高度相等 - 非递归法(层次遍历):通过层次遍历,检查每个节点是否符合满二叉树的条件
代码
递归法
bool IsFullBinaryTree(BTNode* root)
{
// 空树是满二叉树
if (!root)
return true;
// 如果有一个孩子为空,另一个孩子不为空,肯定不是满二叉树
if ((!root->left && root->right) || (root->left && !root->right))
return false;
// 递归判断左子树和右子树是否为满二叉树
return IsFullBinaryTree(root->left) && IsFullBinaryTree(root->right);
}
非递归法
bool IsFullBinaryTree(BTNode* root)
{
if (!root)
return true;
Queue Q;
QueInit(Q);
EnQueue(Q, root);
while (!IsEmpty(Q))
{
BTNode* cur;
DeQueue(Q, cur);
// 如果某个节点有一个孩子为空,另一个不为空,则不是满二叉树
if ((!cur->left && cur->right) || (cur->left && !cur->right))
return false;
// 如果左右孩子都存在,继续遍历
if (cur->left)
EnQueue(Q, cur->left);
if (cur->right)
EnQueue(Q, cur->right);
}
return true;
}
初始化队列:使用队列进行层次遍历,将根节点入队。
逐个检查节点:
如果当前节点有一个孩子为空,另一个孩子不为空,直接返回 false。
如果当前节点有两个孩子,将它们分别入队。
如果当前节点没有孩子或者开始出现子节点为空的情况,则后续所有节点必须为叶子节点,否则返回 false。
遍历完成后,如果未发现不符合的情况,则为满二叉树。