判断一棵树是否为完全二叉树

// 判断一棵树是否为完全二叉树
#include
#include
#include
using namespace std;

const int N = 20;

// 定义树的节点的结构体
struct BTNode
{
	char data; // 数据域
	BTNode* left; // 左孩子指针
	BTNode* right; // 右孩子指针
};

class BTree
{
public:

	// 构造函数
	BTree()
	{
		this->root = NULL; // 初始化根节点为空
	}

	// 利用前序遍历建立二叉树
	void CreateTree(BTNode** root)
	{
		char x;
		cin >> x;
		if (x == '#') *root = NULL;
		else
		{
			*root = new BTNode[N];
			assert(*root); // 断言
			(*root)->data = x; // 给该根节点赋值
			CreateTree(&(*root)->left); // 递归建立左子树
			CreateTree(&(*root)->right); // 递归建立右子树
		}
	}

	// 判断是否为完全二叉树
	bool IsCompleteBTree()
	{
		if (this->root == NULL) return false; // 若根节点为空,则不是完全二叉树
		bool isOnlyLeft = false; // 标记仅有左孩子无有孩子的节点
		queue q; // 创建一个队列存储通过层序遍历出的节点
		q.push(root);
		
		while (!q.empty()) // 若队列非空,则进入循环
		{
			BTNode* cur = q.front(); // 用cur来记录下队头
			q.pop(); // 记录下队头后将队头出队

			if (isOnlyLeft) // 如果标记到了仅有左孩子的节点,则进入这个判断
			{ 
				// 若这是完全二叉树,则标记之后进行判断的节点都应为叶子节点,若有不是叶子节点,则返回false
				if (cur->left || cur->right)
					return false;
			}
			else
			{
				if (cur->left == NULL && cur->right != NULL) // 存在右孩子而无左孩子,一定不是完全二叉树
					return false;
				else if (cur->left != NULL && cur->right == NULL) // 仅存在左孩子,有可能是完全二叉树
				{
					q.push(cur->left); // 将左孩子入队
					isOnlyLeft = true; // 找到仅有左孩子的节点并将其标记
				}
				else if (cur->left != NULL && cur->right != NULL) // 左右孩子都存在,都入队后继续循环判断
				{
					q.push(cur->left);
					q.push(cur->right);
				}
				else if (cur->left == NULL && cur->right == NULL) // 左右孩子都不存在,若这是完全二叉树,则这应该是叶子节点,将其标记继续循环判断
					isOnlyLeft = true;
			}
		}

		return true;
	}

	BTNode* root;
};

int main()
{
	BTree t; // 创建一个二叉树对象
	t.CreateTree(&t.root); // 利用前序遍历建立一棵二叉树

	if (t.IsCompleteBTree()) cout << "YES" << endl; 
	else cout << "NO" << endl;

	return 0;
}

你可能感兴趣的:(数据结构,数据结构,算法,二叉树)