大小堆排序 & Top K 问题
2015-07-29 15:09
489 查看
大小堆排序
堆这种数据结构定义比较简单,大根堆就是父节点的值大于左右子孩子节点的值(小根堆相反),而且利用数组下标就可以很好的表现堆(不过要注意是从0 还是 1开始)。堆常用语实现优先队列,Top K等问题。算法导论第6章对堆的进行了详细讲解,我就不赘述了(看书是不够的,要把思路用代码实现出来才是真的懂了,争取把算法导论上常用的数据结构和算法都自己实现一般)。
大根堆
具体代码(按照算法导论中下标从1开始):
/******* 大小堆排序 & topk问题 ***********/ //调整大根堆(大堆化),数组从1下标开始 void adjust_maxheap(int a[],int size,int i) { int left = i*2; //左节点 int right = i*2+1; //右节点 int max_index; //找根,左,右中最大的节点 if(left < size && a[left]>a[i]) max_index = left; else max_index = i; if(right < size && a[right] > a[max_index]) max_index = right; //如果原来的根不是最大值,则需要交换,交换后原来max值的节点变成了比较小的根 if( i != max_index ) { SWAP(a[i],a[max_index]); adjust_maxheap(a,size,max_index); } } //建立大根堆 void build_maxheap(int a[],int size) { int start = size>>1; //第一个非叶子节点 int i ; for(i = start;i>=1;i--) { adjust_maxheap(a,size,i); } } //大堆排序 void maxheap_sort(int a[],int size) { int i; for(i = size;i>=1;i--) { build_maxheap(a,i); SWAP(a[1],a[i]); } }
测试代码与运行截图:
小根堆
具体代码(下标从0开始):
void adjust_minheap(int a[],int size,int i) { int left = i*2+1; int right = i*2+2; int min_index; if( left < size && a[left]<a[i]) min_index = left; else min_index = i; if( right < size && a[right]< a[min_index]) min_index = right; if( min_index != i) { SWAP(a[i],a[min_index]); adjust_minheap(a,size,min_index); } } void build_minheap(int a[],int size) { int start = size>>1; for(start;start>=0;start--) { adjust_minheap(a,size,start); } } void minheap_sort(int a[],int size) { int i,j=size,last= size -1; for(i = 0;i<size;i++) { build_minheap(a,j--); SWAP(a[0],a[last]); last -= 1; } }
测试代码与运行截图:
运用堆排序解决Top K问题
top k问题就是在一堆数据中选择前K大(前K小)的数据。做法有许多,可以先把所有数据排序,然后选前k个。然后用堆排序解决Top K问题则不用先全部排序,只需维护一个大小为K的堆即可。
实现思路:
如果要选出前K大,则将数据中的前K个元素建立成一个小根堆,从第K+1个元素开始往后依次比较,如果元素大于小根堆的堆顶,那么就和堆顶交换,交换后重新调整为小根堆。这样变量一遍所有数据,最后得到的大小为K的小根堆就是前K大的树。具体代码:
void topk_biggest(int a[],int size,int k) { int i; for(i = k;i<size;i++) { build_minheap(a,k); if(a[i]>a[0]) SWAP(a[i],a[0]); } printf("最大%d个数为:",k); for(i =0;i<k;i++) printf("%d ",a[i]); }
Top k 测试代码&运行截图:
相关文章推荐
- Apache Commons工具集简介
- 使用 Yocto Project 构建自定义嵌入式 Linux 发行版
- linux 0号进程 1号进程 区别(转)
- HDFS架构
- sqoop 学习笔记
- ecshop购买了某商品才能评价且只能评价一次
- 3.网上解决org.apache.commons.lang.xwork.StringUtils的方法都弱爆了,看我怎么解决它!
- linux上安装SVN
- tomcat内存溢出问题详解
- 解密百度2015年5月大量网站被降权原因之站内优化
- OC特有语法—@property
- 删除ecshop分类URL静态重写地址中的b0
- 在Linux下写一个线程池以及线程池的一些用法和注意点
- 在一台电脑上开启多个Tomcat
- shell学习五十五天----进程记账
- 修改ecshop复杂重写里的"+"为"-"
- 如何对ECShop的url路径进行优化
- PHP+Apache如何监控多个端口和配置多站点
- Linux进程使用内存的基本流程---Linux用户进程是如何释放内存的
- 学习笔记:linuxc第七章—进程控制 下篇