unordered_map
1. unordered_map是存儲鍵值對的關聯式容器,其允許通過keys快速的索引到與其對應的 value。
2. 在unordered_map中,鍵值通常用於惟一地標識元素,而映射值是一個對象,其內容與此鍵關聯。鍵 和映射值的類型可能不同。
3. 在內部,unordered_map沒有對按照任何特定的順序排序, 爲了能在常數範圍內找到key所 對應的value,unordered_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)(或者稱散列表)
例如:數據集合{1,7,6,4,5,9};
哈希函數設置爲:hash(key) = key % capacity; capacity爲存儲元素底層空間總的大小。
用該方法進行搜索不必進行多次關鍵碼的比較,因此搜索的速度比較快
哈希衝突
對於兩個數據元素的關鍵字 和 (i != j),有 != ,但有:Hash( ) == Hash( ),即:不同關鍵字通過 相同哈希哈數計算出相同的哈希地址,該種現象稱爲哈希衝突或哈希碰撞。 把具有不同關鍵碼而具有相同哈希地址的數據元素稱爲“同義詞”。
哈希函數
引起哈希衝突的一個原因可能是:哈希函數設計不夠合理。 哈希函數設計原則: 哈希函數的定義域必須包括需要存儲的全部關鍵碼,而如果散列表允許有m個地址時,其值域必須在0 到m-1之間
哈希函數計算出來的地址能均勻分佈在整個空間中
常見哈希函數
1. 直接定製法
取關鍵字的某個線性函數爲散列地址:Hash(Key)= A*Key + B 優點:簡單、均勻 缺點:需要事先 知道關鍵字的分佈情況 使用場景:適合查找比較小且連續的情況
2. 除留餘數法
設散列表中允許的地址數爲m,取一個不大於m,但最接近或者等於m的質數p作爲除數,按照哈希函
數:Hash(key) = key% p(p<=m),將關鍵碼轉換成哈希地址
哈希衝突解決
解決哈希衝突兩種常見的方法是:閉散列和開散列
閉散列
閉散列:也叫開放定址法,當發生哈希衝突時,如果哈希表未被裝滿,說明在哈希表中必然還有空位置,那麼可以把key存放到衝突位置中的“下一個” 空位置中去。
線性探測:從發生衝突的位置開始,依次向後探測,直到尋找到下一個空位置爲止。
插入
假設如上圖,我們要插入一個元素爲44先通過哈希函數計算哈希地址,hashAddr爲4,因此44理論 上應該插在該位置,但是該位置已經放了值爲4的元素,即發生哈希衝突。
通過哈希函數獲取待插入元素在哈希表中的位置 如果該位置中沒有元素則直接插入新元素,如果該位置中有元素髮生哈希衝突,使用線性探測找到下一個空位置,插入新元素
刪除
採用閉散列處理哈希衝突時,不能隨便物理刪除哈希表中已有的元素,若直接刪除元素會影響其他 元素的搜索。比如刪除元素4,如果直接刪除掉,44查找起來可能會受影響。因此線性探測採用標記的僞刪除法來刪除一個元素。
開散列
開散列概念
開散列法又叫鏈地址法(開鏈法),首先對關鍵碼集合用散列函數計算散列地址,具有相同地址的關鍵碼 歸於同一子集合,每一個子集合稱爲一個桶,各個桶中的元素通過一個單鏈錶鏈接起來,各鏈表的頭結 點存儲在哈希表中