这题也太坑了,编号还有两位数的,因此测试点2 3 答案错误
思路:
1.存储结点:
用静态二叉链表数组的方式存储;
2.找根结点:
遍历,hashTable数组,没有被指向过的就是根结点;
判断完全二叉树
3.编号,从左到右、从上到下,从1开始编号。这个顺序正好符合层序遍历。
4.判断:遍历每个结点,看它的左右孩子(若存在)是否符合编号 2*i,2*i+1的规则
5.输出时的最后一个结点怎么找
在层序遍历时,最后记一下last的下标
#define _CRT_SECURE_NO_WARNINGS 1
/**
* 02.25 14:12
* 给出一个树,判断是否为一个完整的二叉树
* 输入:
* N:结点总数,结点从0编号
* N行,每个结点的左右孩子,如果孩子不存在就是 -
* 输出:
* 如果树是一个完整的二叉树,输出YES 和 最后一个结点下标
* 如果不是,输出NO 和 根结点的下标
**/
#include <iostream>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 25; //结点的最大个数
int n; //结点个数
bool hashTable[maxn] = { false };//找根结点用,记录该结点是否被指向过
int last; //记录最后一个结点
struct node {
int data;
int id; //该结点的编号
int lchild;
int rchild;
} Node[maxn]; // 存放结点的node型数组
// 层序遍历,对结点进行编号(从左到右、从上到下,从1开始)
int number = 1;
void layerOrder(int root) {
queue<int> q;
q.push(root);
while (!q.empty()) {
int now = q.front();
q.pop();
Node[now].id = number++;
if (number == n + 1)
last = now;
if (Node[now].lchild != -1)
q.push(Node[now].lchild);
if (Node[now].rchild != -1)
q.push(Node[now].rchild);
}
}
int main() {
scanf("%d", &n);
getchar();
// 录入结点数据
for (int i = 0; i < n; i++) { //数组下标从1开始
Node[i].data = i; //该节点的值
char str[5];
// 输入结点的左右孩子,可能2位数
scanf("%s", str);
if (str[0] == '-') { // 如果第一个输入的是 -
Node[i].lchild = -1;
}else { // 如果输入的不是-,而是数字
int num;
if (strlen(str) == 1) { // 如果是一位数字
num = str[0] - '0';
}
else { // 如果是两位数字
num = (str[0] - '0') * 10 + (str[1] - '0');
}
Node[i].lchild = num; //赋值给当前结点的左孩子
hashTable[num] = true; // 说明这个结点被指向过,不可能是根结点
}
// 同理,录入右孩子 数据
scanf("%s", str);
if (str[0] == '-') {
Node[i].rchild = -1;
}
else {
int num;
if (strlen(str) == 1) {
num = str[0] - '0';
}
else {
num = (str[0] - '0') * 10 + (str[1] - '0');
}
Node[i].rchild = num;
hashTable[num] = true;
}
}
// 找根结点
int root;
for (int i = 0; i < n; i++) {
if (hashTable[i] == false) {
root = i;
break;
}
}
// 层序遍历进行编号
layerOrder(root);
//遍历每个结点,看是否符合完全二叉树的条件,左孩子编号为2x,右孩子编号为2x+1
bool flag = true;
for (int i = 0; i < n; i++) {
//判断左孩子
int left = Node[i].lchild;
if (left != -1) {
if (Node[i].id * 2 != Node[left].id) {
flag = false;
break;
}
}
// 判断右孩子
int right = Node[i].rchild;
if (right != -1) {
if (Node[i].id * 2 + 1 != Node[right].id) {
flag = false;
break;
}
}
}
if (flag == true)
printf("YES %d\n", last);
else
printf("NO %d\n", root);
return 0;
}