unordered系列關聯式容器---底層結構

unordered_map

1. unordered_map是存儲鍵值對的關聯式容器,其允許通過keys快速的索引到與其對應的 value。

2. unordered_map中,鍵值通常用於惟一地標識元素,而映射值是一個對象,其內容與此鍵關聯。鍵 和映射值的類型可能不同。

3. 在內部,unordered_map沒有對按照任何特定的順序排序, 爲了能在常數範圍內找到key所 對應的valueunordered_map將相同哈希值的鍵值對放在相同的桶中。

4. unordered_map容器通過key訪問單個元素要比map快,但它通常在遍歷元素子集的範圍迭代方面效率 較低。

5. unordered_maps實現了直接訪問操作符(operator[]),它允許使用key作爲參數直接訪問value

6. 它的迭代器至少是前向迭代器。

unordered_set

1.unordered_set是不按特定順序存儲唯一元素的容器,並允許根據其值快速檢索單個元素。

2.在unordered_set中,元素的值同時是它的key,可以唯一地標識它。鍵是不可變的,因此,不能在容器中一次修改unordered_set中的元素-儘管可以將它們插入和刪除。

3.在內部,unordered_set中的元素未按任何特定順序排序,而是根據其哈希值組織到存儲桶中,以允許直接通過其快速訪問各個元素(平均平均時間複雜度恆定)。

4.儘管unordered_set容器通過其訪問單個元素的速度要比set容器快,但通常通過它們的子集進行範圍迭代的效率較低。 容器中的迭代器至少是前向迭代器

 

底層結構

unordered系列的關聯式容器之所以效率比較高,是因爲其底層使用了哈希結構。

 

哈希概念

順序結構以及平衡樹中,元素關鍵碼與其存儲位置之間沒有對應的關係,因此在查找一個元素時,必須要經過關鍵碼的多次比較順序查找時間複雜度爲O(N),平衡樹中爲樹的高度,即O( ),搜索的效率取決 於搜索過程中元素的比較次數。

理想的搜索方法:可以不經過任何比較,一次直接從表中得到要搜索的元素如果構造一種存儲結構,通過某種函數(hashFunc)使元素的存儲位置與它的關鍵碼之間能夠建立一一映射的關係,那麼在查找時通過該函 數可以很快找到該元素

 

當向該結構中:

插入元素

         根據待插入元素的關鍵碼,以此函數計算出該元素的存儲位置並按此位置進行存放

搜索元素

        對元素的關鍵碼進行同樣的計算,把求得的函數值當做元素的存儲位置,在結構中按此位置取元素比 較,若關鍵碼相等,則搜索成功

該方式即爲哈希(散列)方法,哈希方法中使用的轉換函數稱爲哈希(散列)函數,構造出來的結構稱爲哈希表 (Hash Table)(或者稱散列表)

例如:數據集合{176459}

哈希函數設置爲:hash(key) = key % capacity; capacity爲存儲元素底層空間總的大小

                                     

用該方法進行搜索不必進行多次關鍵碼的比較,因此搜索的速度比較快

哈希衝突

對於兩個數據元素的關鍵字 和 (i != j),有 != ,但有:Hash( ) == Hash( ),即:不同關鍵字通過 相同哈希哈數計算出相同的哈希地址,該種現象稱爲哈希衝突或哈希碰撞把具有不同關鍵碼而具有相同哈希地址的數據元素稱爲同義詞”。

哈希函數

引起哈希衝突的一個原因可能是:哈希函數設計不夠合理哈希函數設計原則: 哈希函數的定義域必須包括需要存儲的全部關鍵碼,而如果散列表允許有m個地址時,其值域必須在0 到m-1之間

哈希函數計算出來的地址能均勻分佈在整個空間中

 

常見哈希函數

1. 直接定製法

取關鍵字的某個線性函數爲散列地址:HashKey= A*Key + B 優點:簡單、均勻 缺點:需要事先 知道關鍵字的分佈情況 使用場景:適合查找比較小且連續的情況

2. 除留餘數法

設散列表中允許的地址數爲m,取一個不大於m,但最接近或者等於m的質數p作爲除數,按照哈希函

數:Hash(key) = key% p(p<=m),將關鍵碼轉換成哈希地址

 

哈希衝突解決

解決哈希衝突兩種常見的方法是:閉散列開散列

閉散列

           閉散列:也叫開放定址法,當發生哈希衝突時,如果哈希表未被裝滿,說明在哈希表中必然還有空位置,那麼可以把key存放到衝突位置中的下一個空位置中去。

線性探測:從發生衝突的位置開始,依次向後探測,直到尋找到下一個空位置爲止

插入

        假設如上圖,我們要插入一個元素爲44先通過哈希函數計算哈希地址,hashAddr4,因此44理論 上應該插在該位置,但是該位置已經放了值爲4的元素,即發生哈希衝突。

         通過哈希函數獲取待插入元素在哈希表中的位置 如果該位置中沒有元素則直接插入新元素,如果該位置中有元素髮生哈希衝突,使用線性探測找到下一個空位置,插入新元素

 

                                            

刪除

      採用閉散列處理哈希衝突時,不能隨便物理刪除哈希表中已有的元素,若直接刪除元素會影響其他 元素的搜索。比如刪除元素4,如果直接刪除掉,44查找起來可能會受影響。因此線性探測採用標記的僞刪除法來刪除一個元素

開散列

 開散列概念

         開散列法又叫鏈地址法(開鏈法),首先對關鍵碼集合用散列函數計算散列地址,具有相同地址的關鍵碼 歸於同一子集合,每一個子集合稱爲一個桶,各個桶中的元素通過一個單鏈錶鏈接起來,各鏈表的頭結 點存儲在哈希表中

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