题目描述
将一系列给定数字依次插入一个初始为空的小顶堆H[]。随后对任意给定的下标i,打印从H[i]到根结点的路径。
输入格式
每组测试第1行包含2个正整数N和M(≤1000),分别是插入元素的个数、以及需要打印的路径条数。下一行给出区间[-10000, 10000]内的N个要被插入一个初始为空的小顶堆的整数。最后一行给出M个下标。
输出格式
对输入中给出的每个下标i,在一行中输出从H[i]到根结点的路径上的数据。数字间以1个空格分隔,行末不得有多余空格。
输入样例
5 3
46 23 26 24 10
5 4 3
输出样例
24 23 10
46 23 10
26 10
题解
题意理解:给定插入最小堆的序列,根据该序列生成最小堆。读入若干结点下标,输出对应结点到根结点路径上的结点值。
创建空堆与输出结果的函数不用多说,重点在于向堆中插入元素的复现,如下为阉割版。
Insert 函数:
- 传入参数为 堆 与 被插入元素值
- 如果堆满就退出
- 如果堆未满就插入
- 首先 i = ++H->Size ,标记插入到堆尾的下标
- 如果父结点的元素值比待插入元素值大,父结点下滤,当前结点的值替换为父结点的值,当前指针移到父结点
- 直到父结点的值比待插入元素小时退出,当前结点位置就是插入位置
- 退出循环给当前结点赋值
- 插入完成
完整代码(AC):
#include <stdio.h>
#include <stdlib.h>
typedef struct HeapStruct *MinHeap;
struct HeapStruct {
int *Data;
int Size;
int Capacity;
};
void Insert(MinHeap H, int item)
{
int i;
if (H->Size == H->Capacity) return;
else {
for (i = ++H->Size; H->Data[i / 2] > item; i /= 2) {
H->Data[i] = H->Data[i / 2];
}
H->Data[i] = item;
}
}
MinHeap CreateHeap(int n)
{
int i, parent, child, tmp, item;
MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct));
H->Data = (int*)malloc(sizeof(int) * (n + 1));
H->Size = 0;
H->Capacity = n;
H->Data[0] = -10001;
for (i = 1; i <= n; i++) {
scanf("%d", &item);
Insert(H, item);
}
return H;
}
void PrintTrack(MinHeap H, int m)
{
int i, j, index, flag;
for (i = 0; i < m; i++) {
scanf("%d", &index);
flag = 0;
for (j = index; j > 0; j /= 2) {
if (flag) {
printf(" %d", H->Data[j]);
} else {
flag = 1;
printf("%d", H->Data[j]);
}
}
printf("\n");
}
}
void Free(MinHeap H)
{
free(H->Data);
free(H);
}
int main()
{
int n, m;
MinHeap H;
scanf("%d %d", &n, &m);
H = CreateHeap(n);
PrintTrack(H, m);
Free(H);
return 0;
}
第一次尝试时使用读入一组数再调整堆的有序性来建堆。应该先建一个空堆,再逐个插入。
错误解答(WA):
该解答中主要练习了调整完全二叉树有序性的建堆函数。
#include <stdio.h>
#include <stdlib.h>
typedef struct HeapStruct *MinHeap;
struct HeapStruct {
int *Data;
int Size;
};
void BuildHeap(MinHeap H)
{
int i, parent, child, tmp;
for (i = H->Size / 2; i > 0; i--) {
tmp = H->Data[i];
for (parent = i; parent * 2 <= H->Size; parent = child) {
child = parent * 2;
if ((child != H->Size) && (H->Data[child + 1] < H->Data[child]))
child++;
if (tmp <= H->Data[child]) break;
else H->Data[parent] = H->Data[child];
}
H->Data[parent] = tmp;
}
}
MinHeap CreateHeap(int n)
{
MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct));
H->Data = (int*)malloc(sizeof(int) * (n + 1));
H->Size = n;
H->Data[0] = -10001;
for (int i = 1; i <= n; i++) {
scanf("%d", &H->Data[i]);
}
BuildHeap(H);
return H;
}
void PrintTrack(MinHeap H, int m)
{
int i, j, index, flag;
for (i = 0; i < m; i++) {
scanf("%d", &index);
flag = 0;
for (j = index; j > 0; j /= 2) {
if (flag) {
printf(" %d", H->Data[j]);
} else {
flag = 1;
printf("%d", H->Data[j]);
}
}
printf("\n");
}
}
void Free(MinHeap H)
{
free(H->Data);
free(H);
}
int main()
{
int n, m;
MinHeap H;
scanf("%d %d", &n, &m);
H = CreateHeap(n);
PrintTrack(H, m);
Free(H);
return 0;
}