数组形式最小堆的建立以及排序
最小堆
利用数组建立堆之前,需要知道一些理论知识。
利用数组储存时,从1开始,如果一个结点的下标为i, 那么他的左儿子的下标为2i, 他的右儿子的下标为2i+1.
如果一个结点的下标为j
那么它的父结点的下标为 j/2
特别主意,要从a【1】开始储存。
#include <stdio.h> int h[101]; int n; void Swap(int x, int y) //交换h数组中下标为x和y的两个数 { int tmp = h[x]; h[x] = h[y]; h[y] = tmp; } 向下调整函数,以该结点向下调整 调整思路为: 判断该结点的左儿子,右儿子是否比它小,如果小就交换。 交换完之后,以交换的那个儿子结点,继续向下交换。直到没有比它小的儿子或该该点已经没有儿子。 void SiftDown(int i); //创建函数,就是往数组中输入值之后,从最后一个非叶结点开始向下调整,一直到1号根结点 void Creat(void); //删除最小值,就是将堆顶的元素与堆中最后一个元素交换,堆的大小减一, //最后返回刚开始的那个堆顶元素。 int deletmin(void); int main(void) { int i, num; scanf("%d", &num);//结点的总数 for(i = 1; i <= num; i++) { scanf("%d", &h[i]); } n = num; Creat(); for(i = 1; i <= num; i++) printf("%d ", deletmin());//依次删除堆中最小值,并维护堆的性质 //经过调整之后,发现数组h中数已经是有序的,不信可以输出出来看看哟(*^.^*) return 0; } void SiftDown(int i) //从i起点向下调整 { int t, flag = 0; //flag 位需要调整的标志,当儿子中有比其小的,则需要调整 while(i*2 <= n && flag == 0) { if(h[i*2] < h[i]) t = i*2; else t = i; if(h[i*2+1 <= n]) { if(h[i*2+1] < h[t]) t = i*2+1; } if(t != i) { Swap(t, i); i = t; } else flag = 1; } } void Creat(void) { int i; for(i = n/2 ; i >= 1; i--) SiftDown(i); } int deletmin(void) //删除堆顶元素 { int t; t = h[1]; h[1] = h[n]; h[n] = t; n--; SiftDown(1); return t; }