本专栏持续输出数据结构题目集,欢迎订阅。
题目
将一系列给定数字顺序插入一个初始为空的最小堆。随后判断一系列相关命题是否为真。命题分下列几种:
- x is the root:x是根结点;
- x and y are siblings:x和y是兄弟结点;
- x is the parent of y:x是y的父结点;
- x is a child of y:x是y的一个子结点。
输入格式:
每组测试第 1 行包含 2 个正整数 n(≤ 1000)和 m(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间 [−10000,10000] 内的 n 个要被插入一个初始为空的最小堆的整数。之后 m 行,每行给出一个命题。题目保证命题中的结点键值都是存在的。
输出格式:
对输入的每个命题,如果其为真,则在一行中输出 T,否则输出 F。
输入样例:
5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10
输出样例:
F
T
F
T
题目引用自团体程序设计天梯赛真题(2016年)。
代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 1001
#define INF 0x7FFFFFFF
int h[MAXN], size;
int pos[20001]; // 记录每个值在堆中的位置,值范围[-10000,10000],映射到[0,20000]
// 初始化堆
void Create() {
size = 0;
h[0] = -INF; // 哨兵,小于所有可能的元素值
memset(pos, 0, sizeof(pos)); // 初始化位置数组
}
// 插入元素到最小堆
void Insert(int x) {
int i;
for (i = ++size; h[i/2] > x; i /= 2) {
h[i] = h[i/2]; // 上滤
pos[h[i] + 10000] = i; // 更新位置
}
h[i] = x;
pos[x + 10000] = i; // 记录新元素的位置
}
// 判断命题
void Judge(char *statement) {
int x, y;
char op1[20], op2[20], op3[20];
// 解析命题
if (strstr(statement, "is the root")) {
// 情况1: x is the root
sscanf(statement, "%d is the root", &x);
printf("%c\n", (h[1] == x) ? 'T' : 'F');
} else if (strstr(statement, "and") && strstr(statement, "are siblings")) {
// 情况2: x and y are siblings
sscanf(statement, "%d and %d are siblings", &x, &y);
int posX = pos[x + 10000];
int posY = pos[y + 10000];
printf("%c\n", (posX/2 == posY/2) ? 'T' : 'F');
} else if (strstr(statement, "is the parent of")) {
// 情况3: x is the parent of y
sscanf(statement, "%d is the parent of %d", &x, &y);
int posX = pos[x + 10000];
int posY = pos[y + 10000];
printf("%c\n", (posY/2 == posX) ? 'T' : 'F');
} else if (strstr(statement, "is a child of")) {
// 情况4: x is a child of y
sscanf(statement, "%d is a child of %d", &x, &y);
int posX = pos[x + 10000];
int posY = pos[y + 10000];
printf("%c\n", (posX/2 == posY) ? 'T' : 'F');
}
}
int main() {
int n, m, i, x;
char statement[100];
// 读取输入
scanf("%d %d", &n, &m);
// 构建最小堆
Create();
for (i = 0; i < n; i++) {
scanf("%d", &x);
Insert(x);
}
// 处理命题
getchar(); // 消耗掉scanf后的换行符
for (i = 0; i < m; i++) {
fgets(statement, sizeof(statement), stdin);
statement[strcspn(statement, "\n")] = 0; // 去掉换行符
Judge(statement);
}
return 0;
}
288

被折叠的 条评论
为什么被折叠?



