TOP-K排序演算法,從海量不重複資料中找出最大/小的K個數
阿新 • • 發佈:2019-01-08
如題,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大小的情況,我們需要具體再細分下去,具體如何我們可以分情況討論。