海量資料處理 分而治之 hash對映和堆排序

2021-08-26 02:44:06 字數 2715 閱讀 1187

對於海量資料而言,由於無法一次性裝進記憶體處理,導致我們不得不把海量的資料通過hash對映分割成相應的小塊資料,然後再針對各個小塊資料通過hash_map進行統計或其它操作。

什麼是hash對映?

簡單來說,就是為了便於計算機在有限的記憶體中處理big資料,我們通過一種對映雜湊的方式讓資料均勻分布在對應的記憶體位置(如大資料通過取餘的方式對映成小數存放在記憶體中,或大檔案對映成多個小檔案),而這個對映雜湊方式便是我們通常所說的hash函式,設計的好的hash函式能讓資料均勻分布而減少衝突。

什麼是top k?

有n(n>>10000)個整數,求出其中的前k個最大的數。(稱作top k或者top 10)

問題分析:由於(1)輸入的大量資料;(2)只要前k個,對整個輸入資料的儲存和排序是相當的不可取的。

可以利用資料結構的最小堆來處理該問題。

最小堆對於每個非葉子節點的數值,一定不大於孩子節點的數值。這樣可用含有k個節點的最小堆來儲存k個目前的最大值(當然根節點是其中的最小數值)。

每次有資料輸入的時候可以先與根節點比較。若不大於根節點,則捨棄;否則用新數值替換根節點數值。並進行最小堆的調整。

換言之,先對映,而後統計,最後排序。

解法:具體分為以下3個步驟

2.hash_map統計 

當大檔案轉化成了小檔案,那麼我們便可以採用hash_map(ip, value)來分別對1000個小檔案中的ip進行頻率統計,再找出每個小檔案中出現頻率最大的ip。

遍歷map,相同value+1,不同新增key。

if(map.containskey(key)) else

3.堆/快速排序 

統計出1000個頻率最大的ip後,依據各自頻率的大小進行排序(可採取堆排序),找出那個頻率最大的ip,即為所求。

例題2:如何從100萬個數中找出最大的前100個數:

1.堆排序

先取出前100個數,維護乙個100個數的最小堆,遍歷一遍剩餘的元素,在此過程中維護堆就可以了。具體步驟如下: 

step1:取前m個元素(例如m=100),建立乙個小頂堆。保持乙個小頂堆得性質的步驟,執行時間為o(lgm);建立乙個小頂堆執行時間為m*o(lgm)=o(m lgm);       

step2:順序讀取後續元素,直到結束。每次讀取乙個元素,如果該元素比堆頂元素小,直接丟棄 

如果大於堆頂元素,則用該元素替換堆頂元素,然後保持最小堆性質。最壞情況是每次都需要替換掉堆頂的最小元素,因此需要維護堆的代價為(n-m)*o(lgm); 

最後這個堆中的元素就是前最大的100個。時間複雜度為o(n lgm)。

2.分塊查詢 

先把100w個數分成100份,每份1w個數。先分別找出每1w個數裡面的最大的數,然後比較。找出100個最大的數中的最大的數和最小的數,取最大數的這組的第二大的數,與最小的數比較,如果第二個數比最小的那個大則替換掉最小的,否則取第二大數的這組的第二大的數和最小的比較,依次類推。

如何從乙個只有兩個是重複的大陣列中找出那個重複的數:

建立乙個hashset陣列,向裡面新增陣列的每乙個資料,當出現插不進去的時候那個陣列下標就是重複的資料。

例題3:假設目前有一千萬個記錄(這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個。乙個查詢串的重複度越高,說明查詢它的使用者越多,也就是越熱門),請你統計最熱門的10個查詢串,要求使用的記憶體不能超過1g。

hash統計:先對這批海量資料預處理(維護乙個key為query字串,value為該query出現次數的hashtable,即hash_map(query,value),每次讀取乙個query,如果該字串不在table中,那麼加入該字串,並且將value值設為1;如果該字串在table中,那麼將該字串的計數加一即可。最終我們在o(n)的時間複雜度內用hash表完成了統計;

堆排序:第二步、借助堆這個資料結構,找出top k,時間複雜度為n『logk。即借助堆結構,我們可以在log量級的時間內查詢和調整/移動。因此,維護乙個k(該題目中是10)大小的小根堆,然後遍歷300萬的query,分別和根元素進行對比所以,我們最終的時間複雜度是:o(n) + n'*o(logk),(n為1000萬,n』為300萬)。

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

解法:1.分而治之/hash對映 

順序讀取檔案,對於每個詞x,取hash(x)%5000,然後把該值存到5000個小檔案(記為x0,x1,...x4999)中。這樣每個檔案大概是200k左右。當然,如果其中有的小檔案超過了1m大小,還可以按照類似的方法繼續往下分,直到分解得到的小檔案的大小都不超過1m。

2.hash_map統計 

對每個小檔案,採用trie樹/hash_map等統計每個檔案中出現的詞以及相應的頻率。

3.堆/歸併排序 

取出出現頻率最大的100個詞(可以用含100個結點的最小堆)後,再把100個詞及相應的頻率存入檔案,這樣又得到了5000個檔案。最後就是把這5000個檔案進行歸併(類似於歸併排序)的過程了。

乙個非常大的陣列,從中找連續的n個數,求他們的和。

建立乙個新的陣列,新陣列的長度是原陣列長度+1,新陣列的下標0為原陣列下標0之前的和,下標1為原陣列下標1之前的和,依次類推。找連續的n個數,如從第a個數(不是第a個下標)到第b個數,就是求新陣列下標為b減下標為(a-1)的值

海量資料處理 分而治之

對於海量資料而言,由於無法一次性裝進記憶體處理,導致我們不得不把海量的資料通過hash對映分割成相應的小塊資料,然後再針對各個小塊資料通過hash map進行統計或其它操作。那什麼是hash對映呢?簡單來說,就是為了便於計算機在有限的記憶體中處理big資料,我們通過一種對映雜湊的方式讓資料均勻分布在...

海量資料處理專題(三) Hash

什麼是hash hash,一般翻譯做 雜湊 也有直接音譯為 雜湊 的,就是把任意長度的輸入 又叫做預對映,pre image 通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值。這種轉換是一種壓縮對映,也就是,雜湊值的空間通常遠小於輸入的空間,不同的輸入可能會雜湊成相同的輸出,而不可能從雜湊值來...

海量資料處理專題(三) Hash

什麼是hash hash,一般翻譯做 雜湊 也有直接音譯為 雜湊 的,就是把任意長度的輸入 又叫做預對映,pre image 通過雜湊演算法,變換成固定長度的輸出,該輸出就是雜湊值。這種轉換是一種壓縮對映,也就是,雜湊值的空間通常遠小於輸入的空間,不同的輸入可能會雜湊成相同的輸出,而不可能從雜湊值來...