一、哈希表基礎
哈希表是一種不同於常規數組或鏈表的數據結構,通過哈希函數將數據映射到不同的槽位上,使得數據的查找、插入和刪除操作時間複雜度為O(1)。C++ STL中提供了unordered_map和unordered_set兩個哈希表的實現,它們的底層實現都是使用哈希表。
使用哈希表時,我們通常需要關注哈希函數的設計和衝突解決方法。哈希函數應當將數據均勻地分散在不同的槽位上,並且能夠處理不同類型的數據;而衝突解決方法則需要保證數據不會重複,並且插入、刪除時不會影響其他數據。
二、unordered_map用法
unordered_map是C++ STL中實現的哈希表,其使用方法與map基本相同,但相比於map,其查找、插入、刪除的時間複雜度更低且不需要數據排序。以下是unordered_map的簡單示例:
#include #include #include using namespace std; int main() { unordered_map m; m[1] = "hello"; m[2] = "world"; m[3] = "!"; cout << m[2] << endl; // 輸出 world return 0; }
在上述代碼中,我們使用了unordered_map來存儲int和string類型的鍵值對,通過下標訪問map中的元素,並輸出了鍵為2的元素的值。
三、哈希函數設計
哈希函數是哈希表的核心,一個好的哈希函數能夠有效地減少數據衝突。以下是一個簡單的哈希函數設計:
size_t hash_func(const string& str) { size_t hash_value = 0; for (const auto& c : str) { hash_value = 31 * hash_value + c; } return hash_value; }
在上述代碼中,我們採用了djb2哈希算法,將每個字符的ASCII碼乘以一個質數31,並加上前面字符的哈希值,最終得到一個哈希值。
四、哈希衝突解決
當兩個不同的數據被哈希函數映射到同一個槽位時,就會發生哈希衝突。為了解決哈希衝突,我們通常需要使用鏈表、開放尋址等技術。以下是開放尋址法的示例代碼:
template class OpenAddrHashTable { public: explicit OpenAddrHashTable(size_t size = 1000) : size_(size) { table_ = new std::pair[size]; ++size_; } ~OpenAddrHashTable() { delete[] table_; } OpenAddrHashTable(const OpenAddrHashTable&) = delete; OpenAddrHashTable& operator=(const OpenAddrHashTable&) = delete; void insert(const Key& key, const Value& value) { size_t hash_value = hash_func(key); size_t i = hash_value % size_; size_t j = i; while (table_[j].first != key && table_[j].first != Key()) { ++j; if (j == size_) j = 0; if (j == i) throw std::runtime_error("hash table full"); } table_[j] = std::make_pair(key, value); } Value& search(const Key& key) const { size_t i = hash_func(key) % size_; size_t j = i; while (table_[j].first != key && table_[j].first != Key()) { ++j; if (j == size_) j = 0; if (j == i) throw std::runtime_error("key not found"); } return table_[j].second; } private: size_t size_; std::pair* table_; size_t hash_func(const Key& key) const { // 哈希函數的實現 } };
在OpenAddrHashTable中,我們使用了開放尋址法來解決哈希衝突。當數據插入時,如果對應的槽位已經被佔用,就從下一個槽位開始往後查找,直到找到空槽位為止;當數據查找時,如果對應的槽位不是要查找的數據,就繼續從下一個槽位開始往後查找,直到找到要查找的數據或者槽位為空為止。
五、總結
哈希表是一種高效的數據結構,適用於需要快速查找、插入和刪除的場景。C++ STL中通過unordered_map和unordered_set提供了哈希表的實現,我們可以根據業務需求選擇不同的實現方式。同時,針對特定的問題場景,我們也可以自己實現哈希表來達到更好的效果。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/183555.html