PAT 1110 Complete Binary Tree C++ 版

1.题意

给出一棵树的层次遍历+左右子节点,判断其是否是一棵完全二叉树(complete binary tree,后文简称CBT)。

2.分析

判断一棵完全二叉树可以借用层次遍历即可。判断是否为完全二叉树的理论如下:

  • case1:如果节点有右节点但是没有左节点,则肯定不是CBT
  • case2:如果当前节点是最后一个有子树的节点(有左子树或者左右子树都有,但是按照层次遍历的顺序时,其后面的节点却有左子树或者右子树)那么就不是一棵CBT。

3.代码

#include<cstdio>
#include<iostream>
#include<cstring> 
#include<queue>
#define maxn 100
using namespace std;

int N;
int fa[maxn];//每个节点的父节点 [根节点的父节点为0] 
queue<int> que;
int ele;//队中元素 

struct Node{
	int left,right;//左右两个节点
	int data;//当前节点值 
};

Node node[maxn];

//寻找根节点 
int findRoot(int sour){
	while(fa[sour]!=sour){
		sour = fa[sour];
	}
	return sour;
}

//层次遍历 && 是否是一棵Complete Binary Tree 
bool isCBT(int root){
	bool first = false;
	bool flag = true;//是否是一棵CBT 
	que.push(root);//入队列
	while(!que.empty()){//队列非空 
		ele = que.front(); 
		que.pop();//出队 
		if(node[ele].left!=-1) que.push(node[ele].left);
		if(node[ele].right!=-1) que.push(node[ele].right);
		//case 1:左子树不存在,右子树存在的 
		if(node[ele].left==-1 && node[ele].right!=-1){
			flag = false;
		}
		
		//case 2:   
		if(first && (node[ele].left != -1 || node[ele].right!=-1) ){//违反了CBT的规则 
			flag = false;
		}
		if( node[ele].right == -1 && !first ){//如果右子树为null,且尚未置 
			first = true; 
		}
	}	
	return flag;
}

int main(){
	cin >> N;
	int i,j;		
	string left,right;//表示左右两个子树 	
	for(i= 0;i< N;i++){
		fa[i] = i;
	}
	for(i = 0;i< N;i++){		
		cin >> left >> right;
		if(left.compare("-") == 0){
			node[i].left = -1;//左子树为-1
		}
		else {
			node[i].left = stoi(left);
			fa[stoi(left)] = i; 
		}	
		
		if(right.compare("-") == 0){
			node[i].right = -1;//左子树为-1 
		}
		else{
			node[i].right = stoi(right);	
			fa[stoi(right)] = i;
		}
		node[i].data = i;		
	}	
	int root = findRoot(0);
	if(isCBT(root)) {
		cout << "YES "<<ele<<"\n" ;
	}
	else cout <<"NO "<<root<<"\n";
}

4.测试用例

9
7 8
- -
- -
- -
0 1
2 3
4 5
- -
- -

8
- -
4 5
0 6
- -
2 3
- 7
- -
- -


//测只有左子树,没有右子树 
8
- -
4 5
0 - 
- -
2 3
6 7
- -
- -
Yes 0


8
- -
4 5
0 7 
- -
2 3
6 -
- -
- -

5.执行结果

一次AC啦,啦啦啦啦