9.2 二叉树的遍历 A1110 Complete Binary Tree (25 分) 完全二叉树

这题也太坑了,编号还有两位数的,因此测试点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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值