05-树7 堆中的路径

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]);
	}
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值