問題一:
搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為1-255位元組。
假設目前有一千萬個記錄(這些查詢串的重複度比較高,雖然總數是1千萬,但如果除去重複後,不超過3百萬個。乙個查詢串的重複度越高,說明查詢它的使用者越多,也就是越熱門。),請你統計最熱門的10個查詢串,要求使用的記憶體不能超過1g。
分析:
1.
1b(byte) = 8bit
1kb = 1024b
1mb = 1024kb
1gb = 1024mb
故1千萬個長度為1~255位元組的查詢串的大小為 :256*4*250w=1kb*250w 1kb*250w/1024=2441.4mb = 2.38g
規定的記憶體不能超過1g
2.根據原文v_july_v大牛的分析,
第一步:對字串進行hash,這樣可以將一千萬個記錄縮小為三百萬個記錄,這樣就可以將記錄寫入1g記憶體中。
第二步:對hash後的記錄,進行比較。
3.針對第一步hash,給出簡要說明,詳細程式我也會在文章末尾給出
1)資料結構
(1)hash表結構中桶的結構
typedef
struct
_hash_table
hash_table
;(2)hash表的桶中結點的結構
typedef
struct
_node
node
;2)所使用函式
(1)與hash操作有關的函式
/*hash table length is fixed (value is bucket_len)*/
hash_table
*yk_hash_table_init();
/* a ****** hash function */
unsigned
int
yk_******_hash_string(
char
*str,
int
str_len);
node
*yk_find_data_from_hash_table(
hash_table
* hashtb,
type
key,
int
key_len);
status
yk_insert_data_into_hash_table(
hash_table
* hashtb,
type
key,
int
key_len);
void
yk_output_result(
hash_table
* hashtb);
(2)與字串操作有關的函式void
yk_print_str(
char
* str,
int
str_len);
void
yk_cpy_str(
char
*dst,
char
*src,
int
str_len);
int
yk_strcmp(
char
* str1,
char
*str2,
int
len1,
int
len2);
3)簡要說明
hash表這一資料結構,剛入手時真心搞不明白,不知道是為何要發明這一資料結構,也搞不懂如何使用這一資料結構。通過先編寫最基本的hash的操作,大致明白了hash如何操作和如何使用。之後,又嘗試實現topk演算法,進一步了解了hash的用法。
其實hash的用法很簡單,無非就是hash表的初始化+資料插入+資料處理。hash表的初始化不僅僅是固定大小的陣列,也可以是長度可變的。在nginx的hash操作中,就是大小可變的hash表。這兒還是值得學習。
程式說明:
問題二:
給定a、b兩個檔案,各存放50億個url,每個url各佔64位元組,記憶體限制是4g,讓你找出a、b檔案共同的url?
解決方案:
方案1:可以估計每個檔案安的大小為5g×64=320g,遠遠大於記憶體限制的4g。所以不可能將其完全載入到記憶體中處理。考慮採取分而治之的方法。
遍歷檔案a,對每個url求取hash(url)%1000,然後根據所取得的值將url分別儲存到1000個小檔案(記為a0,a1,...,a999)中。這樣每個小檔案的大約為300m。
遍歷檔案b,採取和a相同的方式將url分別儲存到1000小檔案(記為b0,b1,...,b999)。這樣處理後,所有可能相同的url都在對應的小檔案(a0vsb0,a1vsb1,...,a999vsb999)中,不對應的小檔案不可能有相同的url。然後我們只要求出1000對小檔案中相同的url即可。
求每對小檔案中相同的url時,可以把其中乙個小檔案的url儲存到hash_set中。然後遍歷另乙個小檔案的每個url,看其是否在剛才構建的hash_set中,如果是,那麼就是共同的url,存到檔案裡面就可以了。
方案解釋說明:
1)url相同的話,其hash值肯定是相同的,那麼肯定會放入對應的小檔案中。比如說a中的的hash值為105,那麼b中的的hash值也為105。因此所有可能相同的url都在對應的小檔案中(a0-b0,a1-b1)中,不對應的小檔案中不可能有相同的url。
2)在這個解決方案中,遍歷檔案a,根據hash值得到1000個小檔案。模擬到常見的hash操作,1000個小檔案就是1000個桶,也就是1000個鍊錶,這是這兒將其更改為1000個檔案。
程式說明:
參考文獻
資料結構HASH總結二 程式學習篇
在理論學習篇中,我提到要學會hash表初始化 插入元素 查詢元素三大操作。在介紹三大操作之前,首先介紹所用到的資料結構。一 資料結構 1.hash表的結構 接下來介紹的都是hash表的拉鍊法。有兩種hash表的結構,推薦使用結構二。詳細說明見下面。結構一 hash table typedef str...
資料結構 hash
雜湊表 hash table,也叫雜湊表 是根據鍵 key 而直接訪問在記憶體儲存位置的資料結構。分為兩個步驟 hash函式 通過乙個關於鍵值的hash函式,得到所查詢的資料對映到表中乙個位置。訪問資料 不同的key 經過hash函式 可能計算得到相同的輸出。此時叫做衝突,衝突的資料又成乙個表。一般...
Redis資料結構詳解之Hash(四)
hash資料結構累似c 中的dictionary,大家對陣列應該比較了解,陣列是通過索引快速定位到指定元素的,無論是訪問陣列的第乙個元素還是最後乙個元素,所耗費的時間都是一樣的,但是陣列中的索引卻沒有實際意義,他只是乙個位置而已。而我們在查詢某個元素時,一般都會使用有意義的字段來做索引,這就產生啦d...