哈希表的大小为何最好是素数
引言
為什么散列函數采用取模運算?又為什么取模運算的被取模數最好是素數?素數是如何在取模運算中很好的規避沖突的?
這些問題可能困擾諸多程序員很久了。我們總是說素數可以更好的避免沖突,但總是對各種長篇大論的分析望而卻步。
這篇文章是我在學習散列時針對素數在哈希函數中的如何成功避免大量沖突的原因總結。
盡可能言簡意賅地描述為什么素數那么香。
一、結論
素數能夠在取模運算中避免沖突并不是一個數學定律,而且能夠避免沖突也不是絕對的。
從規律上來看,如果待存儲的數列間隔恰好是是被取模數的因子大小,那么合數要比素數更容易呈現周期性的取模重復。
這僅僅是一個規律,目前數學家也無法對這一規律進行嚴格定義,畢竟這個規律也并不是絕對的。
二、演示
我們通過一個簡單的例子來印證一下上面的這個規律:
從規律上來看,如果待存儲的數列間隔恰好是是被取模數的因子大小,那么合數要比素數更容易呈現周期性的取模重復。
這個規律不是絕對的。下面選取了一個合數和一個素數,待存儲的數列間隔為 2 或 3,請仔細觀察規律:
| 1 | 數列間隔 3 (3是12的因子) | 數列 | 34 | 37 | 40 | 43 | 46 | 49 | 52 | 55 | 58 |
| 2 | mod 11 = | 1 | 4 | 7 | 10 | 2 | 5 | 8 | 0 | 3 | |
| 3 | mod 12 = | 10 | 1 | 4 | 7 | 10 | 1 | 4 | 7 | 10 | |
| 4 | mod 13 = | 8 | 11 | 1 | 4 | 7 | 10 | 0 | 3 | 6 | |
| 5 | mod 14 = | 6 | 9 | 12 | 1 | 4 | 7 | 10 | 13 | 2 | |
| 6 | 數列間隔 2 (2是12、14的因子) | 數列 | 67 | 69 | 71 | 73 | 75 | 77 | 79 | 81 | 83 |
| 7 | mod 11 = | 1 | 3 | 5 | 7 | 9 | 0 | 2 | 4 | 6 | |
| 8 | mod 12 = | 7 | 9 | 11 | 1 | 3 | 5 | 7 | 9 | 11 | |
| 9 | mod 13 = | 2 | 4 | 6 | 8 | 10 | 12 | 1 | 3 | 5 | |
| 10 | mod 14 = | 11 | 13 | 1 | 3 | 5 | 7 | 9 | 11 | 13 |
上圖中,數列代表待存儲的整型數據,一般在很多散列表(如HashMap)中,都是通過對關鍵字進行某種變換得到一個整型數字,比如,如果key是字符串,那么可以通過計算字符編碼得到一個整數值。
mod 11 代表對11取模,mod 12 代表對 12 取模,依此類推。
我們分別選取了比較普通的兩組數列,分別對合數(12、14)和素數(11、13)進行取模運算,可以看到,取模結果重復的已經使用紅色標記。
當數列間隔為 3 時,由于 3 是 12 的因子,因此,可以看到表中 mod 12 的結果呈現了周期性的模沖突。而其他的 11、13、14,并沒有發現明顯的沖突問題,而是很好地分散了取模結果。
當數列間隔為 2 時,由于 2 是 12、14 的因子,因此,可以看到表中 mod 12 和 mod 14 的結果都呈現了周期性的模沖突,而 11、13 兩個素數并沒有發現明顯的沖突問題,而是很好地分散了取模結果。
總結
從實驗結果可以清晰的看到,素數要比合數更適合取模運算。在不知道數列間隔的情況下,擁有較少因子的素數可以有效的避免規律性的取模沖突。
大家如果對我的結論感興趣,可以通過對比試驗來嘗試尋找數列間隔與因子之間的關系。
總結
以上是生活随笔為你收集整理的哈希表的大小为何最好是素数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css如何实现一个小三角形,用纯css写
- 下一篇: Spring Cloud —— Feig