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
思路、总结:
- 根据样例分析建堆方式:插入建堆( O(NlogN) )?调整建堆( O(N) )?
- 上手就偷懒没有仔细看样例,用的调整建堆,结果始终过不了。
- 要记住建堆方式不同,父结点的左右儿子结点先后顺序可能是不一样的。
出错代码:
/*将一系列给定数字插入一个初始为空的最小堆H[]
*随后对任意给定的下标i,打印从H[i]到根结点的路径
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct HNode {
int *data; /* 存储元素的数组 */
int size; /* 堆中当前元素个数 */
int capacity; /* 堆的最大容量 */
};
typedef struct HNode *MinHeap;
#define MinData -10001; /* 该值应根据具体情况定义为大于堆中所有可能元素的值 */
MinHeap CreateHeap(int maxSize);
void BuildHeap(MinHeap h);
void PercDown(MinHeap h, int p);
void OutPut(MinHeap h, int m);
int main() {
int n, m, t;
MinHeap h;
scanf_s("%d %d", &n, &m);
if (n < 1 || m<1 || m > 1000) return 0;
h = CreateHeap(n);
for (int i = 1; i <= n; i++) {
scanf_s("%d", &h->data[i]);//将n个元素按输入顺序存入-完全二叉树
h->size++;
}
BuildHeap(h);//调整为最小堆
for (int i = 0; i < m; i++) {
scanf_s("%d", &t);
OutPut(h, t);
printf("\n");
}
return 0;
}
/*********创建容量为maxsize的空的最小堆*********/
MinHeap CreateHeap(int maxSize){
MinHeap h = (MinHeap)malloc(sizeof(struct HNode));
h->data = (int*)malloc((maxSize+1)*sizeof(int));
h->size = 0;
h->capacity = maxSize;
h->data[0] = MinData;/* 定义"哨兵"为小于堆中所有可能元素的值*/
return h;
}
/*****************将完全二叉树调整为最小堆*****************/
/* 调整H->Data[]中的元素,使满足最小堆的有序性 */
void BuildHeap(MinHeap h) {
for (int i = h->size / 2; i > 0; i--) {
PercDown(h, i);
}
}
/* 下滤:将H中以H->Data[p]为根的子堆调整为最小堆 */
void PercDown(MinHeap h, int p) {
int parent, child;
int x;
x = h->data[p];
for (parent = p; parent * 2 <= h->size; parent=child) {
child = parent * 2;
if ((child != h->size) && (h->data[child] > h->data[child+1])) {
child++;//如果左右子树都存在,child指向左右结点的较小者
}
if (x < h->data[child]) {
break;//如果父结点小于child指向的结点,停止循环
}
else {
h->data[parent] = h->data[child];//父结点大于child指向的结点,交换,并下滤
}
}
h->data[parent] = x;
}
/*****************输出函数*****************/
void OutPut(MinHeap h, int t){
for (int child = t; child> 0; child /= 2) {
if(child != 1) printf("%d ", h->data[child]);
else printf("%d", h->data[child]);
}
}