topK問題解法

看風景就發表於2017-11-01

topK問題的最佳解法是堆排,下面介紹用堆排來解決該問題。

堆排解決topK問題的思路,取出前K個數,最重要的就是要減少比較的次數,用堆排維護一個K大小的堆,比如一個小頂堆,則堆頂為堆中最小的值,將堆外的元素依次與堆頂比較,若大於堆頂,則與堆頂交換,並將堆重新調整為小頂堆,依次比較完所有元素。則堆頂為堆中的最小元素,且為所有元素中的第K大的元素,則整個堆則為前K大的K個元素。若要取前K個小的數,則要使用大頂堆。
 
測試程式碼如下:
var array = [10,7,8,6,3,1,5,2,4,9];
var k =6;
var len = array.length;

fHeapSortK(array,len,k);

console.log('topK result: ' + array);

//堆排取出top K資料,小頂堆取最大的前K個資料,大頂堆取最小的前K個資料
function fHeapSortK(data,length,k){
    fBuildSmallHeap(data,k);
    console.log('build ' + data)
    for(var i=k;i<length;i++){
        if(data[i] <= data[0]){
            continue;
        }
        else{
            swap(data,0,i);
            fAdjustSmallHeap(data,0,k-1);
        }
    }
}
//構造小頂堆 function fBuildSmallHeap(data,length){ for(var i = Math.floor(length/2);i--;){ fAdjustSmallHeap(data,i,length); } console.log('small heap ' + data) }
//調整堆為小頂堆 function fAdjustSmallHeap(data,location,length){ var lChild = 2 * location + 1, rChild = 2 * location + 2, smallest; if(lChild <= length && data[lChild] < data[location]){ smallest = lChild; } else{ smallest = location; } if(rChild <= length && data[rChild] < data[smallest]){ smallest = rChild; } if(smallest != location){ swap(data,location,smallest); fAdjustSmallHeap(data,smallest,length); } }
//交換資料 function swap(data,a,b){ var temp = data[a]; data[a] = data[b]; data[b] = temp; }

 

相關文章