关于堆的判断
本专栏持续输出数据结构题目集,欢迎订阅。
文章目录
- 题目
- 代码
题目
将一系列给定数字顺序插入一个初始为空的最小堆。随后判断一系列相关命题是否为真。命题分下列几种:
- 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 0x7FFFFFFFint 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 rootsscanf(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 siblingssscanf(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 ysscanf(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 ysscanf(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;
}