一、算法描述
给定一个二叉树,确定他是否是一个完全二叉树。
完全二叉树的定义:若二叉树的深度为 h,除第 h 层外,其它各层的结点数都达到最大个数,第 h 层所有的叶子结点都连续集中在最左边,这就是完全二叉树。(第 h 层可能包含 [1~2h] 个节点)
示例1
输入:{1,2,3,4,5,6}
返回值:true
示例2
输入:{1,2,3,4,5,#,6}
返回值:false
二、解题思路
为了判断一个二叉树是否为完全二叉树,需要满足以下条件:
对于任意节点,如果其有右孩子但没有左孩子,则不是完全二叉树;
对于任意节点,如果其左子树不为空,但右子树为空,则必须保证其左子树中所有节点都没有左孩子和右孩子;
对于任意节点,当出现第一个没有左孩子或右孩子的节点之后,其后面的节点必须都没有左孩子和右孩子。
在这个算法中,使用了广度优先搜索(BFS)的思想。
首先将根节点加入队列中。当队列不为空时,依次从队列中取出节点,判断是否满足完全二叉树的条件。具体来说,如果当前节点没有左孩子,设置标志位hasNoChild为true;如果当前节点没有右孩子,也设置标志位hasNoChild为true。如果当前节点有左孩子或右孩子,则将其加入队列中。当出现第一个没有左孩子或右孩子的节点之后,其后面的节点必须都没有左孩子和右孩子,因此如果hasNoChild为true,说明该节点不是完全二叉树,返回false。如果队列为空,说明该二叉树是完全二叉树。
最后,在主函数中构造了一棵二叉树,并调用isCompleteTree函数判断是否为完全二叉树。如果是,则输出"The given binary tree is a complete binary tree";否则输出"The given binary tree is not a complete binary tree"。
该算法的时间复杂度为O(n),其中n是树中节点的数量。算法的空间复杂度取决于队列中的元素数量,因此为O(w),其中w是二叉树的宽度(即最大的一层节点数)。在最坏情况下,当二叉树退化为链表时,w = n,因此空间复杂度为O(n)。
三、C++代码实现
#include <iostream>
#include <queue>
using namespace std;
// 定义二叉树的节点结构体
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
bool isCompleteTree(TreeNode* root) {
if (root == NULL) {
return true;
}
queue<TreeNode*> q;
q.push(root);
bool hasNoChild = false;
while (!q.empty()) {
TreeNode* node = q.front();
q.pop();
if (node->left == NULL) {
hasNoChild = true;
} else if (hasNoChild) {
return false;
} else {
q.push(node->left);
}
if (node->right == NULL) {
hasNoChild = true;
} else if (hasNoChild) {
return false;
} else {
q.push(node->right);
}
}
return true;
}
};
int main() {
// 测试样例
TreeNode* root = new TreeNode(1);
root->left = new TreeNode(2);
root->right = new TreeNode(3);
root->left->left = new TreeNode(4);
root->left->right = new TreeNode(5);
root->right->right = new TreeNode(6);
Solution s;
if (s.isCompleteTree(root)) {
cout << "The given binary tree is a complete binary tree" << endl;
} else {
cout << "The given binary tree is not a complete binary tree" << endl;
}
return 0;
}