第九節:哈希表(初階)

1. 哈希表的核心概念

哈希表(Hash Table)是一種通過哈希函數將鍵(Key)映射到存儲桶(Bucket)的數據結構,核心目標是實現快速查找、插入和刪除操作。其核心特點如下:

  • ?哈希函數:將任意長度的鍵轉換為固定長度的索引(通常取模運算)。
    index = hash(key) % bucket_count;
  • ?沖突解決:當不同鍵映射到同一索引時,通過鏈表、開放尋址法等方式處理沖突。
  • ?平均時間復雜度
    • 插入、查找、刪除:?O(1)(理想情況,無沖突)。
    • 最壞情況(所有鍵沖突):?O(n)(退化為鏈表)。


?2. C++ 哈希表的實現容器

C++ STL 提供了兩種主要的哈希表容器:

容器特性適用場景
unordered_map鍵值對存儲,支持快速訪問、插入、刪除。鍵唯一,值可修改。需要鍵值對且頻繁查詢的場景
unordered_set存儲唯一鍵,僅支持快速查詢、插入、刪除。需要快速判斷元素是否存在
?示例代碼
#include <iostream>
#include <unordered_map>
#include <unordered_set>int main() {// std::unordered_map 示例std::unordered_map<std::string, int> word_count;word_count["hello"] = 5;word_count["world"] = 3;std::cout << "Count of 'hello': " << word_count["hello"] << std::endl; // 輸出 5// std::unordered_set 示例std::unordered_set<char> vowels = {'a', 'e', 'i', 'o', 'u'};std::cout << std::boolalpha << vowels.count('a') << std::endl; // 輸出 truereturn 0;
}

?3. 哈希表的內部機制

?3.1 哈希函數
  • ?默認哈希函數:STL 使用模板類?std::hash,但對自定義類型需手動定義哈希函數。
  • ?自定義哈希函數:通過特化?std::hash?或傳遞自定義哈希函數對象。
    // 自定義哈希函數示例(字符串)
    namespace std {template<> struct hash<string> {size_t operator()(const string& s) const {size_t h = 0;for (char c : s) h = h * 131 + c; // 簡單哈希算法return h;}};
    }
?3.2 沖突解決策略

C++ 哈希表采用鏈地址法?(Chaining)處理沖突:

  • 每個桶(Bucket)存儲一個鏈表(或動態數組),所有哈希到同一索引的鍵值對按順序存儲。
  • ?負載因子?(Load Factor):
    float load_factor = (total_elements) / (bucket_count);
    當負載因子超過閾值(默認 1.0),容器會自動擴容并重新哈希(Rehash)。

?4. 哈希表的性能分析

?指標?描述
?時間復雜度- 平均:O(1)
- 最壞:O(n)(哈希沖突嚴重時)
?空間復雜度O(n)(需額外空間存儲桶和鏈表節點)
?優點- 插入、查找、刪除速度快。
- 支持動態擴容。
?缺點- 哈希沖突影響性能。
- 不保證元素順序。
- 內存占用較高。
?性能優化技巧
  1. ?選擇好的哈希函數:減少沖突概率(如使用雙哈希、混合哈希)。
  2. ?調整負載因子:通過?max_load_factor?控制擴容頻率。
    std::unordered_map<int, int> map;
    map.max_load_factor(0.7); // 負載因子不超過 70%
  3. ?預分配桶數量:減少動態擴容次數。
    std::unordered_map<int, int> map(1000); // 預分配 1000 個桶

?5. 哈希表的應用場景

?場景?推薦容器?原因
字符串到整數的映射std::unordered_map快速查找字符串對應的值(如字典)
元素存在性判斷std::unordered_setO(1) 時間復雜度判斷元素是否存在
數據緩存std::unordered_map鍵值對緩存高頻訪問數據
布隆過濾器(Bloom Filter)自定義哈希表快速過濾不存在的數據(需配合位數組)

?6. 哈希表 vs 其他數據結構

?對比維度?哈希表?平衡二叉搜索樹(如?std::map)?
?查找速度平均 O(1),最壞 O(n)O(log n)
?插入/刪除速度平均 O(1),最壞 O(n)O(log n)
?內存占用較高(桶和鏈表開銷)較低(僅節點存儲)
?有序性無序有序(按鍵排序)
?適用場景高頻查詢、去重需要有序遍歷或范圍查詢

?7. 常見問題與注意事項

  1. ?哈希沖突攻擊

    • 攻擊者構造特定鍵使哈希表退化為鏈表,導致性能下降。
    • 解決方案:使用加密哈希函數(如?std::"crypto::sha256)或增加鹽值(Salt)。
  2. ?鍵的比較

    • 默認使用?operator==?和?std::hash,自定義類型需同時特化這兩個函數。
    // 自定義類型 Person
    struct Person {std::string name;int age;bool operator==(const Person& other) const {return name == other.name && age == other.age;}
    };// 特化 std::hash
    namespace std {template<> struct hash<Person> {size_t operator()(const Person& p) const {return hash<string>()(p.name) ^ hash<int>()(p.age);}};
    }
  3. ?性能瓶頸

    • 頻繁的哈希沖突會導致性能下降,需通過優化哈希函數或增加桶數量解決。

?8. 總結

C++ 哈希表(std::unordered_map/std::unordered_set)是高效的數據結構,適用于需要快速訪問去重的場景。其核心在于哈希函數的設計和沖突處理策略,實際使用中需根據數據特點調整參數(如負載因子、桶數量)以優化性能。對于追求有序性的場景,建議使用?std::map(紅黑樹實現),而哈希表則在追求速度時更優。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/73298.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/73298.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/73298.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Visio使用教程】

Visio使用教程 1. Visio 的基本介紹1.1 Visio 是什么&#xff1f;核心特點&#xff1a; 1.2 主要功能與應用場景典型用途&#xff1a;行業應用&#xff1a; 1.3 版本與兼容性1.4 Visio下載1.5 安裝 2. Visio 的界面與基礎操作2.1 界面布局詳解2.2 創建新文檔與模板選擇2.3 形狀…

緩存使用的具體場景有哪些?緩存的一致性問題如何解決?緩存使用常見問題有哪些?

緩存使用場景、一致性及常見問題解析 一、緩存的核心使用場景 1. 高頻讀、低頻寫場景 典型場景&#xff1a;商品詳情頁、新聞資訊、用戶基本信息。特點&#xff1a;數據更新頻率低&#xff0c;但訪問量極高。策略&#xff1a; Cache-Aside&#xff08;旁路緩存&#xff09;&a…

谷歌 Gemini 2.0 Flash實測:1條指令自動出圖+配故事!

今天看到很多人夸Gemini 2.0 Flash的能力很強。 強大的P圖能力&#xff0c;改背景、換衣服、調整姿態、表情控制等等 其中最讓人眼前一亮的是圖文功能。 它不僅是理解圖文&#xff0c;而是能根據文字描述創作出一整個的故事、步驟圖文。 我上手試了一下&#xff0c;感覺效果…

雷電模擬器連接Android Studio步驟

打開雷電模擬器&#xff0c;點擊桌面系統應用—>打開設置—>關于平板電腦→連續點擊5次版本號&#xff0c;會出現開發者選項—->進入開發者選項—->勾選打開usb調試。 命令行提示符&#xff0c;進入雷電模擬器安裝目錄。然后執行 Plain Text adb.exe connect 127.0…

配置普通鏈接二維碼規則 校驗文件檢查失敗

配置普通鏈接二維碼規則 校驗文件檢查失敗 1.問題 2.解決思路&#xff1a; 直接訪問地址&#xff0c;不跳轉文本&#xff0c;感覺是nginx配置問題打開服務器nginx 域名默認走80端口&#xff0c;配置了指定的訪問路徑&#xff0c;命令行 nginx -t ,nginx -s reload,start ngin…

c語言經典基礎編程題

c語言經典基礎編程題 一、輸出輸出1.1溫度輸出1.2排齊數據1.3進制轉換 二、選擇分支2.1求最大值2.2成績評定2.3分段函數求值2.4 利潤計算2.5判斷閏年2.6二次方程根 三、循環結構3.1倒數求和3.2最大數3.3判斷素數3.4判斷完全數3.5打印菱形&#x1f680;&#x1f680;&#x1f68…

java數據處理:Map<String, Object>、Map<String, List<Room>>、Map<String, Integer>

已知數據都存在WargameConfig.HallMap里。 一、Map<String, Integer> 需求:按照scenarioName進行分類,統計每種scenarioName下的Room對象有多少; 思路:統計一個名為WargameConfig.HallMap的集合中,每個不同場景名稱(scenarioName)出現的次數。返回一個鍵值對映射…

安全的實現數據備份和恢復

&#x1f4d5;我是廖志偉&#xff0c;一名Java開發工程師、《Java項目實戰——深入理解大型互聯網企業通用技術》&#xff08;基礎篇&#xff09;、&#xff08;進階篇&#xff09;、&#xff08;架構篇&#xff09;清華大學出版社簽約作家、Java領域優質創作者、CSDN博客專家、…

TCP網絡協議

TCP粘包 1. TCP在接收數據時&#xff0c;多包數據粘在了一起 2. 原因&#xff1a; 1. TCP發送數據時&#xff0c;沒有及時發走&#xff0c;會根據緩沖區數據的情況進行重新組包&#xff1b; 2. TCP接收方&#xff0c;沒有及時讀走緩沖區數據&#xff0c;導致緩沖區大量數…

ES6回顧:閉包->(優點:實現工廠函數、記憶化和異步實現)、(應用場景:Promise的then與catch的回調、async/await、柯里化函數)

閉包講解 ES6回顧&#xff1a;閉包->(優點&#xff1a;實現工廠函數、記憶化和異步實現&#xff09;、&#xff08;應用場景&#xff1a;Promise的then與catch的回調、async/await、柯里化函數&#xff09; 以下是與 JavaScript 閉包相關的常見考點整理&#xff0c;結合 Pro…

OpenMCU(三):STM32F103 FreeRTOS移植

概述 本文主要描述了STM32F103移植FreeRTOS的簡要步驟。移植描述過程中&#xff0c;忽略了Keil軟件的部分使用技巧。默認讀者熟練使用Keil軟件。本文的描述是基于OpenMCU_RTOS這個工程&#xff0c;該工程已經下載放好了移植STM32F103 FreeRTOS的所有文件 OpenMCU_RTOS工程的愿景…

生成對抗網絡(GAN)原理與應用

目錄 一、引言 二、GAN的基本原理 &#xff08;一&#xff09;生成器&#xff08;Generator&#xff09;的工作機制 &#xff08;二&#xff09;判別器&#xff08;Discriminator&#xff09;的工作機制 &#xff08;三&#xff09;對抗訓練的過程 三、GAN在AIGC生圖中的應…

STM32 內置的通訊協議

數據是以幀為單位發的 USART和UART的區別就是有沒有同步功能 同步是兩端設備有時鐘連接&#xff0c;異步是沒時鐘連接&#xff0c;靠約定號的頻率&#xff08;波特率&#xff09;接收發送數據 RTS和CTS是用來給外界發送已“可接收”或“可發送”信號的&#xff0c;一般用不到…

ES 使用geo point 查詢離目標地址最近的數據

需求描述&#xff1a;項目中需要通過經緯度坐標查詢目標地所在的行政區。 解決思路大致有種&#xff0c;使用es和mysql分別查詢。 1、使用es進行查詢 將帶有經緯度坐標的省市區數據存入es中&#xff0c;mappings字段使用geo point類型&#xff0c;索引及查詢dsl如下。 geo p…

Appium等待機制--強制等待、隱式等待、顯式等待

書接上回&#xff0c;Appium高級操作--其他操作-CSDN博客文章瀏覽閱讀182次&#xff0c;點贊6次&#xff0c;收藏7次。書接上回Appium高級操作--從源碼角度解析--模擬復雜手勢操作-CSDN博客。https://blog.csdn.net/fantasy_4/article/details/146162851主要講解了Appium的一些…

【架構藝術】Go語言微服務monorepo的代碼架構設計

近期因為項目架構升級原因&#xff0c;筆者著手調研一些go項目monorepo的代碼架構設計&#xff0c;目標是長期把既有微服務項目重要的部分都轉移到monorepo上面&#xff0c;讓代碼更容易維護&#xff0c;協作開發更加方便。雖然經驗不多&#xff0c;但既然有了初步的調研&#…

深入解析 JVM —— 從基礎概念到實戰調優的全鏈路學習指南

文章目錄 一、為什么要學習 JVM&#xff1f;1. 面試必備與技能提升2. 性能優化與問題診斷3. 編寫高質量代碼 二、JVM 基礎概念與體系結構1. JVM 簡介2. JDK、JRE 與 JVM 三、JVM 內存模型1. 線程私有區2. 線程共享區 四、類加載機制與雙親委派1. 類加載過程2. 雙親委派模型3. 動…

前端及后端實現csv文件下載功能

方法一、 前端內容&#xff1a; const url window.URL.createObjectURL(new Blob([res.data])); const link document.createElement(a); link.href url; const fileNameDateTime getFormattedDateTime(); const filename "用戶提現列表"fileNameDateTime.csv…

QT中委托QStyledItemDelegate的使用

目錄 一、子類化委托 二、委托方法實現 1)createEditor 2)setEditorData 3)setModelData 4)updateEditorGeometry 三、委托使用 四、總結 Qt的數據容器控件采用模型/視圖(model/view)架構設計。模型用于存放控件的數據,視圖則用于顯示編輯數據,而委托則是…

OpenCV實現視頻背景提取

在計算機視覺領域&#xff0c;背景減除&#xff08;Background Subtraction&#xff09;是一種常用的技術&#xff0c;用于從視頻序列中提取前景對象。 背景減除的核心思想是通過建模背景&#xff0c;然后將當前幀與背景模型進行比較&#xff0c;從而分離出前景對象。 OpenCV…