这里把所有关于堆的操作写出来。当做标程吧。
#include<stdio.h>
#include<stdlib.h>
#define ms 1025
typedef struct _heap
{
int a[ms];
int size;
}heap;
heap h;
static void _shift(heap *h, int i)
{
int j, t, *a = h ? h->a : 0, n = h ? h->size : 0;
if (!h) return;
t = a[i];
while ((j = (i<<1)+1) < n)
{
if (j < n - 1 && a[j] > a[j+1]) ++j;
if (a[j] < t) { a[i] = a[j]; i = j; }
else break;
}
a[i] = t;
}
static void _increase_key(heap *h, int i, int key)
{
int j, t, *a = h ? h->a : 0, n = h ? h->size : 0;
if (!h) return;
t = a[i] = key;
while ((j = (i>>1)) >= 0 && j != i)
{
if (a[j] > t) { a[i] = a[j]; i = j; }
else break;
}
a[i] = t;
}
void build_heap(heap *h)
{
int i = 0, *a = h ? h->a : 0, n = h ? h->size : 0;
if (!h) return;
for (i = (n - 2) >> 1; i >= 0; --i) _shift(h, i);
}
int pop(heap *h)
{
int m, *a = h ? h->a : 0, n = h ? h->size : 0;
if (!h || 0 == n) return -1;
m = a[0]; a[0] = a[n-1]; h->size--;
_shift(h, 0);
return m;
}
void push(heap *h, int v)
{
int *a = h ? h->a : 0, n = h ? h->size : 0;
if (!h) return;
h->size ++;
_increase_key(h, h->size - 1, v);
}
int main(void)
{
int i = 0, n, v;
while (scanf("%d", &n) != EOF)
{
h.size = 0;
for (i = 0; i < n; ++i)
{
scanf("%d", &v);
push(&h, v);
}
build_heap(&h);
while (h.size > 1)
printf("%d ", pop(&h));
printf("%d\n", pop(&h));
}
return 0;
}
习题
1、2、3、
4、
b 排序之后再进行计算,或者用最小堆,每次取最小的数来求和。
c 建立一个100万个数的堆
d 实际上是归并排序,在算法导论中也有提及,就是把这k个要归并的,建立成为k元堆,每次取出最小的,并把这个最小的所在链的下一个加入堆中。
5、没看明白
6、7、值得研究