字典的本質(zhì)

NSDictionary(字典)是使用hash表來實(shí)現(xiàn)key和value之間的映射和存儲(chǔ)的。字典的底層是通過hash表實(shí)現(xiàn)的。

hash表:將key代入一個(gè)函數(shù)m中得到值是value在表n中存儲(chǔ)的位置。這個(gè)函數(shù)m稱為hash函數(shù),這個(gè)表n稱為hash表。

三:哈希存儲(chǔ)過程

1.根據(jù) key 計(jì)算出它的哈希值 h。

2.假設(shè)箱子的個(gè)數(shù)為 n,那么這個(gè)鍵值對應(yīng)該放在第 (h % n) 個(gè)箱子中。

3.如果該箱子中已經(jīng)有了鍵值對,就使用開放尋址法或者拉鏈法解決沖突。

在使用拉鏈法解決哈希沖突時(shí),每個(gè)箱子其實(shí)是一個(gè)鏈表,屬于同一個(gè)箱子的所有鍵值對都會(huì)排列在鏈表中。

哈希表還有一個(gè)重要的屬性: 負(fù)載因子(load factor),它用來衡量哈希表的空/滿程度,一定程度上也可以體現(xiàn)查詢的效率,計(jì)算公式為:

負(fù)載因子 = 總鍵值對數(shù) / 箱子個(gè)數(shù)

負(fù)載因子越大,意味著哈希表越滿,越容易導(dǎo)致沖突,性能也就越低。因此,一般來說,當(dāng)負(fù)載因子大于某個(gè)常數(shù)(可能是 1,或者 0.75 等)時(shí),哈希表將自動(dòng)擴(kuò)容。

哈希表在自動(dòng)擴(kuò)容時(shí),一般會(huì)創(chuàng)建兩倍于原來個(gè)數(shù)的箱子,因此即使 key 的哈希值不變,對箱子個(gè)數(shù)取余的結(jié)果也會(huì)發(fā)生改變,因此所有鍵值對的存放位置都有可能發(fā)生改變,這個(gè)過程也稱為重哈希(rehash)。

哈希表的擴(kuò)容并不總是能夠有效解決負(fù)載因子過大的問題。假設(shè)所有 key 的哈希值都一樣,那么即使擴(kuò)容以后他們的位置也不會(huì)變化。雖然負(fù)載因子會(huì)降低,但實(shí)際存儲(chǔ)在每個(gè)箱子中的鏈表長度并不發(fā)生改變,因此也就不能提高哈希表的查詢性能。

基于以上總結(jié),細(xì)心的朋友可能會(huì)發(fā)現(xiàn)哈希表的兩個(gè)問題:

1.如果哈希表中本來箱子就比較多,擴(kuò)容時(shí)需要重新哈希并移動(dòng)數(shù)據(jù),性能影響較大。

2.如果哈希函數(shù)設(shè)計(jì)不合理,哈希表在極端情況下會(huì)變成線性表,性能極低。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容