[编程珠玑读书笔记]堆排序,小根堆

堆排序的关键是要实现siftup和siftdown。当建立完这两个函数以后,排序一个数组只需要5行代码。算法执行了n-1次siftup和siftdown,而每次操作的成本最多O(lgn),所以运行时间为O(nlogn)。

#include <stdio.h> #include <stdlib.h> #define MAX 20 void swap( int *data, int i, int j) { int temp = data[i]; data[i] = data[j]; data[j] = temp; } //siftup比较好理解,将每一个元素都与自己的父亲比较,如果自己的值小于父亲的值,就互换,直到到堆顶,或父亲的值小于自己的值为止。 void siftup(int *data, int n ) { int i = n; int p; while( 1 ) { if ( i == 1 ) break; p = i/2; if( data[p] <= data[i]) break; swap( data, i, p ); i = p; } } //这里的n其实意义不大,是指n之后的数据是符合要求的,n之前的数据可能不满足小根堆的要求,调整的方法也是从堆顶开始,初步向小调整 void siftdown( int *data, int n) { int i = 1; int c = 0; while( 1 ) { c = 2 * i; if( c > n ) break; //取两个孩子中较小的一个与自己作比较 if( c + 1 <= n && data[ c + 1] < data[c] ) c++; //如果孩子的值小于自己的值,则互换 if( data[i] <= data[c] ) break; swap( data, c, i); i = c; } } int main() { int data[ MAX + 1]; int i= 0; srand(5); for( i = 1; i <= MAX; i++ ) data[i] = rand() % 500; //建堆 for( i = 2; i <= MAX; i++ ) siftup(data,i); //从后向前调整 for( i =MAX; i >= 2; i--) { swap(data, 1, i); siftdown(data, i - 1 ); } for( i = 1; i < MAX; i++ ) printf("%d\t", data[i]); printf("\n"); return 0; }


堆排序与系统排序的效率比较:

#include <stdio.h> #include<iostream> #include<string.h> #include <algorithm> #include <stdlib.h> using namespace std; #define MAX 200000 void swap( int *data, int i, int j) { int temp = data[i]; data[i] = data[j]; data[j] = temp; } //siftup比较好理解,将每一个元素都与自己的父亲比较,如果自己的值小于父亲的值,就互换,直到到堆顶,或父亲的值小于自己的值为止。 void siftup(int *data, int n ) { int i = n; int p; while( 1 ) { if ( i == 1 ) break; p = i/2; if( data[p] <= data[i]) break; swap( data, i, p ); i = p; } } //这里的n其实意义不大,是指n之后的数据是符合要求的,n之前的数据可能不满足小根堆的要求,调整的方法也是从堆顶开始,初步向小调整 void siftdown( int *data, int n) { int i = 1; int c = 0; while( 1 ) { c = 2 * i; if( c > n ) break; //取两个孩子中较小的一个与自己作比较 if( c + 1 <= n && data[ c + 1] < data[c] ) c++; //如果孩子的值小于自己的值,则互换 if( data[i] <= data[c] ) break; swap( data, c, i); i = c; } } int main() { double BegTime, EndTime; int data[ MAX + 1]; int data2[ MAX + 1]; data2[0] = 0; int i= 0; srand(5); for( i = 1; i <= MAX; i++ ) data[i] = rand() % 500; memcpy( data2, data, MAX+1); BegTime = clock(); //建堆 for( i = 2; i <= MAX; i++ ) siftup(data,i); //从后向前调整 for( i =MAX; i >= 2; i--) { swap(data, 1, i); siftdown(data, i - 1 ); } EndTime = clock(); printf("HeapSort:%gms\n", (EndTime - BegTime) / 1000); BegTime = clock(); sort(data2, data2 + MAX + 1); EndTime = clock(); printf("sort: %gms\n", (EndTime - BegTime) / 1000); printf("\n"); return 0; }
测试结果如下:

HeapSort:60ms
sort: 40ms

结果表明,堆排序确实有着相当不错的表现,不到必须的时候,还是应当使用系统的sort函数,效率很高,且节约开发成本。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值