实验目的:
在代码实践中,加强写数据结构与算法代码的能力,加深对于堆作为一种实用结构的理解。
预期效果:
第一次输入两个数(以空格为间隔)分别作为数据总数m与要找出的最小的数的个数n,第二次输入m个数(以空格为间隔),按“第n个最小数:x\n”的格式输出结果。
实验思路:
前提:所有参与的数字均为正整数。
使用数组存储所输入的数据,使用堆结构的下渗算法将数组建成最小堆,然后输出。
因为建堆的时间为O(n),所以在处理类似找最小或最大数据的应用场景中,使用堆这一工具,可以提高程序效率。
当然,实验中应用的方法并不是堆排序的最好方法,仅供参考。
实验代码:
#include <stdio.h>
#include <stdlib.h>
/* 最小堆实现 */
#define ElementType int
struct HNode {
ElementType *data;
int currentSize;
int capacity;
};
typedef struct HNode *MinHeap;
#define MINDATA -1 // 哨兵元素定义
MinHeap createMinHeap(int capacity) {
MinHeap minH = (MinHeap)malloc(sizeof(struct HNode));
minH->data = (ElementType *)malloc((capacity+1)*sizeof(ElementType));
minH->currentSize = 0;
minH->capacity = capacity;
minH->data[0] = MINDATA;
return minH;
}
int isEmpty(MinHeap H) {
return (H->currentSize==0);
}
int isFull(MinHeap H) {
return (H->currentSize==H->capacity);
}
void percolateDown (MinHeap H, int root) {
int currentLocation = root;
int minChild;
ElementType rootValue = H->data[root];
for (;currentLocation*2<=H->currentSize;currentLocation=minChild) {
minChild = currentLocation*2;
if (minChild!=H->currentSize&&H->data[minChild]>H->data[minChild+1]) {
minChild++;
}
if (rootValue<=H->data[minChild]) {
break;
}
else {
H->data[currentLocation] = H->data[minChild];
}
}
H->data[currentLocation] = rootValue;
}
void insert(MinHeap H, ElementType X) {
if (isFull(H)) puts("Error! Heap is full.");
else {
int insertLocator = ++H->currentSize;
for (;H->data[insertLocator/2]>X;insertLocator/2) {
H->data[insertLocator] = H->data[insertLocator/2];
}
H->data[insertLocator] = X;
}
}
ElementType popTop(MinHeap H) {
if (isEmpty(H)) {
puts("Error! Heap is full.");
return -1;
}
else {
ElementType topValue = H->data[1];
H->data[1] = H->data[H->currentSize--];
percolateDown(H,1);
return topValue;
}
}
MinHeap buildMinHeap(ElementType *elements, int capacity) {
MinHeap ret = createMinHeap(capacity);
ret->currentSize = capacity;
for (int i=1;i<=capacity;i++) {
ret->data[i] = elements[i-1];
}
for (int i=ret->currentSize;i>0;i--) {
percolateDown(ret,i);
}
return ret;
}
/* 最小堆实现 完 */
/* 主程序 */
int main() {
// 读入数据
int numCount,minCount;
scanf("%d %d",&numCount,&minCount);
if (minCount>numCount) {
puts("Error! 最小数个数不应超过数据总个数。");
getchar();
getchar();
return 1;
}
else {
printf("输入成功!将要找出%d个数中的%d个最小数\n",numCount,minCount);
int elements[numCount];
for (int i=0; i<numCount; i++) {
scanf("%d",&elements[i]);
}
// 建立最小堆
MinHeap heap = buildMinHeap(elements,numCount);
// 输出结果
for (int i=0; i<minCount; i++) {
printf("第%d个最小数:%d\n",i+1,popTop(heap));
}
getchar();
getchar();
return 0;
}
}