1. 程式人生 > >1102:散列表(中)

1102:散列表(中)

目錄

面試題目:如何設計一個工業級的雜湊函式?

一、如何設計雜湊函式?

二、如何根據裝載因子動態擴容?

三、如何選擇雜湊衝突解決方法?


面試題目:如何設計一個工業級的雜湊函式?

思路

何為一個工業級的散列表?工業級的散列表應該具有哪些特性?結合學過的知識,我覺的應該有這樣的要求:

1.支援快速的查詢、插入、刪除操作;

2.記憶體佔用合理,不能浪費過多空間;

3.效能穩定,在極端情況下,散列表的效能也不會退化到無法接受的情況。

方案

如何設計這樣一個散列表呢?根據前面講到的知識,我會從3個方面來考慮設計思路:

1.設計一個合適的雜湊函式;

2.定義裝載因子閾值,並且設計動態擴容策略;

3.選擇合適的雜湊衝突解決方法。

知識總結

一、如何設計雜湊函式?

1.要儘可能讓雜湊後的值隨機且均勻分佈,這樣會盡可能減少雜湊衝突,即便衝突之後,分配到每個槽內的資料也比較均勻。

2.除此之外,雜湊函式的設計也不能太複雜,太複雜就會太耗時間,也會影響到散列表的效能。

3.常見的雜湊函式設計方法:直接定址法、平方取中法、摺疊法、隨機數法等。

二、如何根據裝載因子動態擴容?

1.如何設定裝載因子閾值?

①可以通過設定裝載因子的閾值來控制是擴容還是縮容,支援動態擴容的散列表,插入資料的時間複雜度使用攤還分析法。

②裝載因子的閾值設定需要權衡時間複雜度和空間複雜度。如何權衡?如果記憶體空間不緊張,對執行效率要求很高,可以降低裝載因子的閾值;相反,如果記憶體空間緊張,對執行效率要求又不高,可以增加裝載因子的閾值。

2.如何避免低效擴容?分批擴容

①分批擴容的插入操作:當有新資料要插入時,我們將資料插入新的散列表,並且從老的散列表中拿出一個數據放入新散列表。每次插入都重複上面的過程。這樣插入操作就變得很快了。

②分批擴容的查詢操作:先查新散列表,再查老散列表。

③通過分批擴容的方式,任何情況下,插入一個數據的時間複雜度都是O(1)。

三、如何選擇雜湊衝突解決方法?

1.常見的2中方法:開放定址法和連結串列法。

2.大部分情況下,連結串列法更加普適。而且,我們還可以通過將連結串列法中的連結串列改造成其他動態查詢資料結構,比如紅黑樹、跳錶,來避免散列表時間複雜度退化成O(n),抵禦雜湊衝突攻擊。

3.但是,對於小規模資料、裝載因子不高的散列表,比較適合用開放定址法。