05-树7 堆中的路径 (25分)
题目描述
将一系列给定数字插入一个初始为空的小顶堆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
解题思路
直接根据输入序列建立小顶堆,然后根据下标打印出到根节点的路径即可。
代码
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1000 //小顶堆的容量
#define MINVALUE -10001 //小顶堆的哨兵值,放在下标为0的位置
struct HeapStruct {
int *data; //用数组来表示完全二叉树
int size; //当前堆中的结点数
};
typedef struct HeapStruct *MinHeap;
MinHeap createHeap(); //创建堆
void insertHeap(MinHeap heap, int data); //向堆中插入元素
int main() {
int N, M;
scanf("%d %d", &N, &M);
MinHeap heap = createHeap();
for (int i = 0; i < N; i++) {
int data;
scanf("%d", &data);
insertHeap(heap, data); //读取N个值,将它们依次插入堆中
}
for (int i = 0; i < M; i++) {
int index;
scanf("%d", &index);
for ( ; index >= 1; index /= 2) { //通过下标除以2来找到父结点,直到下标为1
if (index == 1) printf("%d\n", heap->data[index]);
else printf("%d ", heap->data[index]);
}
}
}
MinHeap createHeap() {
MinHeap minHeap = (MinHeap) malloc(sizeof(struct HeapStruct)); //为堆分配空间
minHeap->data = (int *) malloc((MAXSIZE + 1) * sizeof(int)); //为数组分配空间,注意大小为最大容量+1,因为0放的哨兵值
minHeap->size = 0;
minHeap->data[0] = MINVALUE; //下标0放哨兵值
return minHeap;
}
void insertHeap(MinHeap heap, int data) {
if (heap->size == MAXSIZE) return;
heap->data[++heap->size] = data;
int i = heap->size;
for ( ; heap->data[i / 2] > data; i /= 2) {
heap->data[i] = heap->data[i / 2]; //将插入值与父结点比较,若父结点大则下浮
}
heap->data[i] = data;
}