20170927_利用大根堆求出最小的K个数

来源:互联网 发布:鬼才电影 知乎 编辑:程序博客网 时间:2024/06/04 01:20

20170927_利用大根堆求出最小的K个数


当数据量比较大而内存一次性装不下的时候,想要对求出数据中最小的K个数,
则可以采用大根堆,维护一个含有K个数的大根堆,这个堆中的所有元素就是所求。
首先,读入K个数创建一个大小为K的大根堆,然后依次读入后序的数据,依次与大根堆的堆顶元素比较,
若大于堆顶元素,则直接抛弃该元素、读入下一个元素。
若小于堆顶元素,则该元素属于最小的K个元素之一,需要用它来替换堆顶元素,然后再从堆顶元素开始维护这个大根堆。
直到所有元素都比较完为止,这个堆中的所有元素就是所求。


//大根堆的应用_数组中查找最小的K个数/*当数据量比较大而内存一次性装不下的时候,想要对求出数据中最小的K个数,则可以采用大根堆,维护一个含有K个数的大根堆,这个堆中的所有元素就是所求。首先,读入K个数创建一个大小为K的大根堆,然后依次读入后序的数据,依次与大根堆的堆顶元素比较,若大于堆顶元素,则直接抛弃该元素、读入下一个元素。若小于堆顶元素,则该元素属于最小的K个元素之一,需要用它来替换堆顶元素,然后再从堆顶元素开始维护这个大根堆。直到所有元素都比较完为止,这个堆中的所有元素就是所求。*/#include<iostream>#include<vector>#include<string>#include<algorithm>#include<numeric>#include<functional>using namespace std;//建立大根堆——>自上而下的重新调整堆结构void Sift(int r[], int k, int m){int i=k;//需要调整的节点是k=iint j=2*i;//节点j 是节点i 的左孩子节点int temp=0;//堆中最后一个结点的编号是m(m=n),节点总个数while(j<=m)//筛选还没有进行最后一个节点时{if(j<m && r[j]<r[j+1])//比较节点i的左右孩子,j为较大者++j;if(r[i]>r[j])//如果根节点i值已经大于左右孩子中的最大值,直接退出即可break;else//否则,需要交换根节点和左右孩子中的最大值的那个节点{temp=r[i];r[i]=r[j];r[j]=temp;i=j;//被筛节点位于原来节点j的位置j=2*i;//自上向下调整,i始终是被筛的节点}}}//建立大根堆——>循环建立void CreatBigHeap(int r[], int n){for(int i=n/2; i>=1; --i)//共n个元素,从最后一个非叶子节点开始筛Sift(r, i, n);//每次筛的节点是i}//主函数int main(void){int k=0;cin>>k;//最小的K个数int r[]={1,2,8,7,3,4,6,5};int *B=new int(k);for(int i=0; i<k; ++i)B[i]=r[i];CreatBigHeap(B, k);for(int i=k; i<sizeof(r)/sizeof(r[0]); ++i){if(r[k]>=B[i])//若大于堆顶元素continue;else//若小于堆顶元素{B[i]=r[i];Sift(B, 1, k);}}system("pause");return 0;}


原创粉丝点击