本专栏持续输出数据结构题目集,欢迎订阅。
题目
请编写程序,将 n 个已经满足 d 叉最小堆顺序约束的数据直接读入最小堆;随后将下一个读入的数据 x 插入堆;再执行删顶操作并输出删顶的元素;最后顺次输出堆中剩余元素以检验操作的正确性。
输入格式:
输入在第 1 行给出 2 个正整数 c(2<c≤1000)和 d(1<d≤4),依次对应最小堆的最大容量和树的度;下一行给出正整数 n(<c);随后一行按层序遍历的顺序给出 n 个最小堆元素;最后一行给出将要插入堆的元素 x。所有堆元素均为 int 型范围内的整数。
输出格式:
在一行中输出插入后再删顶的元素,格式为 min = y,其中 y 为删顶元素值。
随后 n 行,按层序遍历的顺序每行输出一个最小堆元素。
输入样例:
10 3
9
1 3 4 6 7 10 8 5 9
2
输出样例:
min = 1
2
3
4
6
7
10
8
5
9
代码
#include <stdio.h>
#include <stdlib.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 向上调整,维护d叉最小堆性质
void siftUp(int arr[], int n, int d, int i) {
while (i > 0) {
int parent = (i - 1) / d;
if (arr[i] >= arr[parent]) break;
swap(&arr[i], &arr[parent]);
i = parent;
}
}
// 向下调整,维护d叉最小堆性质
void siftDown(int arr[], int n, int d, int i) {
while (1) {
int smallest = i;
int startChild = d * i + 1;
int endChild = startChild + d;
for (int j = startChild; j < endChild && j < n; j++) {
if (arr[j] < arr[smallest]) {
smallest = j;
}
}
if (smallest == i) break;
swap(&arr[i], &arr[smallest]);
i = smallest;
}
}
int main() {
int c, d, n;
scanf("%d %d", &c, &d);
scanf("%d", &n);
int *heap = (int *)malloc(c * sizeof(int));
if (heap == NULL) {
fprintf(stderr, "内存分配失败\n");
return 1;
}
for (int i = 0; i < n; i++) {
scanf("%d", &heap[i]);
}
int x;
scanf("%d", &x);
// 插入新元素
heap[n] = x;
siftUp(heap, n + 1, d, n);
n++;
// 删顶操作
int min = heap[0];
heap[0] = heap[n - 1];
n--;
siftDown(heap, n, d, 0);
// 输出结果
printf("min = %d\n", min);
for (int i = 0; i < n; i++) {
printf("%d\n", heap[i]);
}
return 0;
}