书接上回,在我们了解堆排序之后,我们便可以接着学习topk排序方法了。这是一种较为高效的算法,用来获取一堆数中最大的内几个。
具体做法:
1.创建k大小的小顶堆
在上次的文章中,我们主要使用了大顶堆,其实小顶堆也差不多,只需要在原来的向下调整函数中修改两个符号即可。
2.将其他数与根循环做比较
我们首先将数组的前几个元素构造成了小顶堆结构,那么根一定是目前k个数中第k大的数,如果之后的数比根大,那么就做交换,然后向下调整一次,继续恢复小顶堆,然后循环这个过程,这样就找到了前k大的数。
鉴于只是在堆排序的基础上做了少量改动,下面直接放出代码:
#include <iostream>
using namespace std;
void sift (int a[], int low , int high) //小顶堆向下调整函数
{
int temp = a[low];
int i = low;
int j = 2*i+1;
while(j<=high)
{
if(a[j+1]<a[j]&&j+1<=high)
j = j+1;
if(a[j]<temp)
{
a[i]=a[j];
i = j;
j = 2*j+1;
}
else
{
a[i] = temp;
break;
}
}
if(j>high)
a[i]=temp;
}
void swap(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
void topk_sort(int a[],int k,int size)
{
for(int i = (k-2)/2 ; i > -1 ;i-- ) //只用管前k个元素就行
{
sift(a,i,k-1);
}
for(int j = k ; j<size ; j++) //循环比较,如果大于堆顶就换位
{
if(a[j]>a[0])
{
swap(a[j],a[0]);
sift(a,0,k-1);
}
}
}
int main()
{
int a[] = {1,4,5,6,7,3,2,8,9};
topk_sort(a,4,sizeof(a)/sizeof(int));
for(int i = 0;i<sizeof(a)/sizeof(int);i++)
{
cout<<a[i];
}
}