13. 散列表(中):如何打造一個工業級水平的散列表


面試題目:如何設計一個工業級的散列函數?
思路:
何爲一個工業級的散列表?工業級的散列表應該具有哪些特性?結合學過的知識,我覺的應該有這樣的要求:
1.支持快速的查詢、插入、刪除操作;
2.內存佔用合理,不能浪費過多空間;
3.性能穩定,在極端情況下,散列表的性能也不會退化到無法接受的情況。
方案:
如何設計這樣一個散列表呢?根據前面講到的知識,我會從3個方面來考慮設計思路:
1.設計一個合適的散列函數;
2.定義裝載因子閾值,並且設計動態擴容策略;
3.選擇合適的散列衝突解決方法。
知識總結:
一、如何設計散列函數?
1.要儘可能讓散列後的值隨機且均勻分佈,這樣會盡可能減少散列衝突,即便衝突之後,分配到每個槽內的數據也比較均勻。
2.除此之外,散列函數的設計也不能太複雜,太複雜就會太耗時間,也會影響到散列表的性能。
3.常見的散列函數設計方法:直接尋址法、平方取中法、摺疊法、隨機數法等。
二、如何根據裝載因子動態擴容?
1.如何設置裝載因子閾值?
①可以通過設置裝載因子的閾值來控制是擴容還是縮容,支持動態擴容的散列表,插入數據的時間複雜度使用攤還分析法。
②裝載因子的閾值設置需要權衡時間複雜度和空間複雜度。如何權衡?如果內存空間不緊張,對執行效率要求很高,可以降低裝載因子的閾值;相反,如果內存空間緊張,對執行效率要求又不高,可以增加裝載因子的閾值。
2.如何避免低效擴容?分批擴容
①分批擴容的插入操作:當有新數據要插入時,我們將數據插入新的散列表,並且從老的散列表中拿出一個數據放入新散列表。每次插入都重複上面的過程。這樣插入操作就變得很快了。
②分批擴容的查詢操作:先查新散列表,再查老散列表。
③通過分批擴容的方式,任何情況下,插入一個數據的時間複雜度都是O(1)。
三、如何選擇散列衝突解決方法?
①常見的2中方法:開放尋址法和鏈表法。
②大部分情況下,鏈表法更加普適。而且,我們還可以通過將鏈表法中的鏈表改造成其他動態查找數據結構,比如紅黑樹、跳錶,來避免散列表時間複雜度退化成O(n),抵禦散列衝突攻擊。
③但是,對於小規模數據、裝載因子不高的散列表,比較適合用開放尋址法。

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