大數據處理之哈希表(二)--出現頻率最多的top xxx 位

上篇文章中只是求了出現頻次最高的值,可是大數據處理往往需求的是top 10 ,top 100或者某一段區間的數據。
顯然只定義一個Hash a是不能放下的。如果是求出現頻次top100呢?最起碼定義 Hash arr[100]吧。
比如拿計數器10000長度和數據範圍爲32767來說。
我們最少要分4次,分別是數據取餘4後  0  1  2 3的四種情況
第一次餘數爲0,即4的倍數這一組,我們是不是要先算出這組的top100,然後再和下組餘數爲1的top100相比,
這時候你應該想起的什麼吧。這組的top100是有序的,而下組的top100也是有序的,兩個有序數列合成一個有序數列,歸併算法應該爲首選。
上面說的只是如何把各分組top100變成整個top100。

但並沒有說每組的top100該如何選擇。每組的top100都要從10000萬個計數器數據裏提取出來,我們學習過的衆多內部排序誰最適合做這種選出前幾位的事情?  印象中最快的歸併或快排嗎?顯然不是,他倆都是整體處理全部數據,而我們的需求是什麼?只要前面的100個最大的,其他9900個數據的死活我們不管。
是不是選擇排序很適合?每次選出最大的或最小的?而選擇排序裏的堆排序是不是對簡單選擇排序的進一步升級?因此我們就使用堆排序來做這件事。
 可是。如果使用堆排序,還能使用整型數組的計數器嗎?我們知道我們是靠計數器的下標和原始數據確立某種關係的。這種關係就是i*r+j。 可是堆排序的堆調整把計數器的計數次數調整了,下標卻不會動。
具體來說就是如果使用int數組計數器,10000個計數器元素排下來,最後100個數據的確是最大的。可是這100個數據的下標原先對應的數據我們根本找不到了,因爲我們之前是靠下標確定數據多少的。如果按照原先代碼運行。得到的結果始終會是出現頻次最高的100數據是該組最大的100個數據。這顯然是錯誤的。
因此爲了解決這種問題,我們必須再添加一個元素保存原始數據是多少。那麼計數器的類型是不是可以更改爲
Hash count[10000];  既記錄的數據的出現次數。也記錄了數據是多少。使用堆排序後。count最後100位的
count[n].num 可以獲取到原先的數據。

定義下代碼頭

這個全局變量Hash a[100]數組就是我們最終要的top100所在地。

思路說完了,那麼該從何入手呢。
我們先開始修改堆排序把,修改有2個內容,一是讓它適應hash,二是隻讓它算出100位後停止。
不清楚堆排序的可以看看堆排序。在此不多贅述

heapsort里加了第三個參數n。這個n就代表要求出n個最大數 放在傳入的arr數組中的後100位。

每組的top100出來後,並不是真正的top100,要與之前確定好的top100歸併。
歸併算法老生常談了。無需多述。



然後是主要代碼,(一些具體說明在圖中)




結果如下:








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章