摘要:本文簡要介紹了top-k(求一個序列中前K個最大或最小的元素)算法的二分實現方法,並給出了C++源
代碼
關鍵字:top-k,二分,快排序
網上介紹top-k算法的博文貌似不多,有一個搜索引擎中排名靠前的top-k算法介紹中給出了源碼,
我試了試,發現有點小BUG,就自己整理了一下,先說說實現原理,後麵給出源碼。
top-k的實現方法比較常見的有堆和二分法,這裏隻介紹二分實現方法,具體思路如下:
以求長度為N的整數數組中前K個最大數為例,類似於快排序,本方法遞歸地把數組分為兩部分
(設劃分點索引為M),將大的數放到左邊部分,將小的數放到右邊部分。如果M大於K
對數組0~(M-1)部分執行top-k算法;如果M小於等於K,計上一次劃分點索引為LAST, 對數組0~LAST
進行快排序。運行結束後,數組的0~(K-1)即為最大的K個整數!算法的時間複雜度為O(N*log2K),適合
數據可以全部裝入內存的情形!
源碼如下(VC++ 6.0編譯測試通過):
/*
* 二分實現top-k算法
* 取長度為N的整數數組中前K個最大的數
*/
#include <iostream>
#include <ctime>
using namespace std;
#define MAX_NUM 1000
#define N 200
#define K 20
/* global data */
int array[N];
/* funcitons declaration*/
void init_array(int n);
void print_result(int n);
void quicksort(int low, int high);
void topk(int low, int high, int k);
/* main */
int main(int argc, char* *argv)
{
cout<<"init array,size:"<<N<<"......"<<endl;
init_array(N);
print_result(N);
cout<<"generate top-"<<K<<"......"<<endl;
topk(0, N - 1, K);
cout<<"result....."<<endl;
print_result(K);
system("pause");
return 0;
}
/* function definition */
void init_array(int n)
{
for(int i = 0; i < n; ++i)
{
array[i] = rand() % MAX_NUM;
}
}
void print_result(int n)
{
for(int i = 0; i < n; ++i)
{
cout<<array[i]<<" ";
}
cout<<endl;
}
void mswap(int i, int j)
{
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
void quicksort(int low, int high)
{
if(low >= high) return;
mswap(low, rand() % (high - low + 1) + low);
int m = low;
for(int i = low + 1; i <= high; ++i)
{
if(array[i] > array[low])
{
mswap(++m, i);
}
}
mswap(m, low);
quicksort(low, m - 1);
quicksort(m + 1, high);
}
void topk(int low, int high, int k)
{
static int last = high;
if(low >= high) return;
mswap(low, rand() % (high - low + 1) + low);
int m = low;
for(int i = low + 1; i <= high; ++i)
{
if(array[i] > array[low])
{
mswap(++m, i);
}
}
mswap(m, low);
if(k < m)
{
last = m;
topk(low, m - 1, k);
}
else
{
quicksort(low, last);
}
}