1. 程式人生 > >TOP-K排序演算法,從海量不重複資料中找出最大/小的K個數

TOP-K排序演算法,從海量不重複資料中找出最大/小的K個數

如題,TOP-K排序的主要功能是找出一堆不重複資料中的最小或最大的幾個數,此處我們介紹這種型別題目的某種解法:

最大最小堆,最大堆結構裡面的每一個數不都是小於root的值麼?和我們要解決的問題很像。由此,我們可以構造一個堆,並且用它來儲存我們需要找的那幾個數。有這麼一個動態flash就很好地揭示了其中關係: top-k動畫演示

關於什麼是堆在此就不做介紹了,但注意,此處所用的的最大最小堆和資料結構的推排序的堆有區別,不再贅述。下面給出一個例子來供參考:(C++程式碼)

#include<stdio.h>
#include<iostream>
using namespace std;
struct min_heap{
    min_heap(int n){
        this->size=n;
        for(int i=0;i<size;i++) heap[i]=-1;
    }
    int size;
    int heap[100];
    void add(int n){
        if(n<=heap[0]) return;
        int tem=0;
        heap[0]=n;
        while(tem<size){
            if(2*tem+1>=size) break;
            if(2*tem+2>=size&&heap[tem]<heap[2*tem+1]) break;
            if(2*tem+2>=size&&heap[tem]>heap[2*tem+1]){
                int chan=heap[tem];
                heap[tem]=heap[2*tem+1];
                heap[2*tem+1]=chan;
                break;
            }
            if(heap[tem]<heap[2*tem+1]&&heap[tem]<heap[2*tem+2]) break;
            else{
                int min= 2*tem+1;
                if(heap[min]>heap[2*tem+2]) min=2*tem+2;
                int chan=heap[tem];
                heap[tem]=heap[min];
                heap[min]=chan;
                tem=min;
            }
        }
    }
    void print(){
        for(int i=0;i<size;i++){
            if(heap[i]>0) cout<<heap[i]<<" ";
        }
        cout<<endl;
    }

};


//測試用例:
int main(){
    int a[12]={145436,2234,113,4,5,6,7,8,9,23,45,67};
    min_heap* test=new min_heap(4);
    for(int i=0;i<12;i++){
        test->add(a[i]);
        test->print();
    }
    test->print();
    return 0;
}
  結果如下圖:

舉個例子:

有一個1G大小的一個檔案,裡面每一行是一個詞,詞的大小不超過16位元組,記憶體限制大小是1M。返回頻數最高的100個詞。

大資料的題有這麼一個模式:先hash縮小,然後hash統計,然後排序。

此題,記憶體只有2××20b,資料共2××30b,假設每個詞皆2××4b,我們可以推出記憶體一次可以存2××16個數據,總資料2××26個,我們可以hash%1024分成1024堆(hash等於某值就儲存之),每堆大小大約1M,在1024堆裡面統計詞頻,然後用上述K-tops求出結果。

當然,也有可能出現某堆不止1m大小的情況,我們需要具體再細分下去,具體如何我們可以分情況討論。