std::unorderd_map 簡介

1. unorderd_map 簡介

  • 1. unorderd_map 簡介
    • 簡介
    • 1.1. 實現原理
    • 1.2. 函數
    • 1.3. 問題集
      • 1.3.1. emplace、emplace_hint、insert 的區別
    • 1.4. 參考鏈接

簡介

  • unordered_map 是 C++ 標準庫中的一個容器,它定義在 <unordered_map> 頭文件里。它借助哈希表來存儲鍵值對,能快速查找、插入和刪除元素
  • 快速查找:平均情況下,查找、插入和刪除操作的時間復雜度為 O ( 1 ) O(1) O(1)。不過在最壞情況下,例如哈希沖突嚴重時,時間復雜度會達到 O ( n ) O(n) O(n)
  • 無序存儲:unordered_map 不會按照鍵的順序存儲元素,元素的存儲順序由哈希函數決定。
  • 鍵的唯一性:每個鍵在 unordered_map 中是唯一的。若嘗試插入已存在的鍵,新的值會覆蓋舊的值。

1.1. 實現原理

  • 底層實現主要基于哈希表(Hash Table)
  1. 哈希函數
  • unordered_map 使用哈希函數將鍵轉換為一個無符號整數,這個整數將作為數組的索引。
  • 對于基本數據類型(如 int、string 等),標準庫已經提供了默認的哈希函數。
  • 但對于自定義類型,需要用戶自己定義哈希函數。

例如,對于自定義類型 MyKey,可以這樣定義哈希函數:

#include <functional>struct MyKey {int a;double b;// 重載相等運算符,用于比較鍵是否相等bool operator==(const MyKey& other) const {return a == other.a && b == other.b;}
};// 自定義哈希函數
struct MyKeyHash {std::size_t operator()(const MyKey& k) const {// 使用 std::hash 對不同成員進行哈希,然后組合auto h1 = std::hash<int>{}(k.a);auto h2 = std::hash<double>{}(k.b);return h1 ^ (h2 << 1);}
};
  1. 哈希桶(Bucket)
  • 哈希表通常由一個數組構成,數組中的每個元素稱為一個哈希桶。
  • 每個哈希桶可以存儲一個或多個鍵值對,當多個鍵通過哈希函數映射到同一個桶時,就會發生哈希沖突。
  1. 處理哈希沖突
  • 哈希沖突是指不同的鍵通過哈希函數映射到了同一個桶。
  • unordered_map 通常使用鏈地址法(Separate Chaining)來處理哈希沖突。
  • 在鏈地址法中,每個哈希桶實際上是一個鏈表(或其他容器,如紅黑樹),當發生哈希沖突時,新的鍵值對會被添加到對應的鏈表中。

以下是一個簡單的示意圖,哈希表數組:

+--------+--------+--------+
| Bucket0| Bucket1| Bucket2|
+--------+--------+--------+
| Node1  | Node3  | Node4  |
| Node2  |        |        |
+--------+--------+--------+

在這個示意圖中,Bucket0 發生了哈希沖突,有兩個鍵值對(Node1 和 Node2)被映射到了這個桶中,它們通過鏈表連接在一起。

  1. 插入操作
  • 向 unordered_map 中插入一個鍵值對時,會執行以下步驟:
  • 使用哈希函數計算鍵的哈希值。
  • 根據哈希值找到對應的哈希桶。
  • 檢查該桶中是否已經存在相同的鍵,如果存在,則更新對應的值;如果不存在,則將新的鍵值對插入到桶中(通常是鏈表的頭部)。
  1. 查找操作
  • 當查找一個鍵對應的值時,會執行以下步驟:
  • 使用哈希函數計算鍵的哈希值。
  • 根據哈希值找到對應的哈希桶。
  • 遍歷該桶中的鏈表(或其他容器),查找是否存在與給定鍵相等的鍵。如果找到,則返回對應的值;如果未找到,則返回一個表示未找到的標記(如 end() 迭代器)。
  1. 刪除操作
  • 刪除操作與查找操作類似,首先找到對應的哈希桶,然后遍歷桶中的鏈表,找到要刪除的鍵值對并將其從鏈表中移除。
  1. 負載因子(Load Factor)和擴容
  • 負載因子是指哈希表中元素的數量與哈希桶數量的比值。
  • 當負載因子超過某個閾值(通常是 1.0)時,為了減少哈希沖突,提高查找效率,unordered_map 會進行擴容操作。
  • 擴容時,會創建一個更大的哈希表數組,然后將原有的鍵值對重新哈希到新的數組中。

總結:unordered_map 通過哈希表實現了快速的鍵值對查找、插入和刪除操作。它使用哈希函數將鍵映射到哈希桶,通過鏈地址法處理哈希沖突,并在負載因子過高時進行擴容。這種實現方式使得 unordered_map 在平均情況下具有 O(1) 的時間復雜度。

1.2. 函數

  • 成員方法

  • 迭代器

    • begin 返回指向容器中第一個鍵值對的正向迭代器。
    • end 返回指向容器中最后一個鍵值對之后位置的正向迭代器。
    • cbegin 和 begin 功能相同,只不過在其基礎上增加了 const 屬性,即該方法返回的迭代器不能用于修改容器內存儲的鍵值對。
    • cend 和 end 功能相同,只不過在其基礎上,增加了 const 屬性,即該方法返回的迭代器不能用于修改容器內存儲的鍵值對。
  • CRUD操作

    • operator[key] 該模板類中重載了 [] 運算符,只要給定某個鍵值對的鍵 key,就可以獲取該鍵對應的值。注意,如果當前容器中沒有以 key 為鍵的鍵值對,則其會使用該鍵向當前容器中插入一個新鍵值對。

    • at(key) 返回容器中存儲的鍵 key 對應的值,如果 key 不存在,則會拋出 out_of_range 異常。

    • find(key) 查找以 key 為鍵的鍵值對,如果找到,則返回一個指向該鍵值對的正向迭代器;反之,則返回一個指向容器中最后一個鍵值對之后位置的迭代器(end 方法返回的迭代器)。

    • count(key) 在容器中查找以 key 鍵的鍵值對的個數。

    • equal_range(key) 返回一個 pair 對象,其包含 2 個迭代器,用于表明當前容器中鍵為 key 的鍵值對所在的范圍。

    • emplace 向容器中添加新鍵值對,直接在容器內部構造元素,避免了不必要的拷貝或移動,效率比 insert 方法高。

    • emplace_hint 向容器中添加新鍵值對,接受一個迭代器 position 作為提示參數,用于提高插入效率,但提示錯誤可能會降低效率。

    • insert 向容器中添加新鍵值對,通常需要先構造好 value_type 對象,然后將其插入容器,可能會涉及額外的拷貝或移動操作。

    • erase 刪除指定鍵值對。可以通過鍵、迭代器位置或迭代器范圍來指定要刪除的元素。

    • clear 清空容器,即刪除容器中存儲的所有鍵值對。

  • 屬性

    • empty 若容器為空,則返回 true;否則 false。
    • size 返回當前容器中存有鍵值對的個數。
    • max_size 返回容器所能容納鍵值對的最大個數,不同的操作系統,其返回值亦不相同。
  • 類函數

    • swap 交換 2 個 unordered_map 容器存儲的鍵值對,前提是必須保證這 2 個容器的類型完全相等。
  • 底層 hash 相關函數

    • bucket_count 返回當前容器底層存儲鍵值對時,使用桶(一個線性鏈表代表一個桶)的數量。
    • max_bucket_count 返回當前系統中,unordered_map 容器底層最多可以使用多少桶。
    • bucket_size(n) 返回第 n 個桶中存儲鍵值對的數量。
    • bucket(key) 返回以 key 為鍵的鍵值對所在桶的編號。
    • load_factor 返回 unordered_map 容器中當前的負載因子。負載因子,指的是的當前容器中存儲鍵值對的數量(size)和使用桶數(bucket_count)的比值,即 load_factor = size / bucket_count。
    • max_load_factor 返回或者設置當前 unordered_map 容器的負載因子。
    • rehash(n) 將當前容器底層使用桶的數量設置為 n。
    • reserve 將存儲桶的數量(也就是 bucket_count 方法的返回值)設置為至少容納count個元(不超過最大負載因子)所需的數量,并重新整理容器。
    • hash_function 返回當前容器使用的哈希函數對象。

1.3. 問題集

1.3.1. emplace、emplace_hint、insert 的區別

  • 構造方式:
    • insert:通常需要先構造好 value_type 對象,然后將其插入容器,可能會涉及額外的拷貝或移動操作。
    • emplace 和 emplace_hint:直接在容器內部構造元素,避免了不必要的拷貝或移動,效率更高。
  • 提示參數:
    • insert 和 emplace:不需要提示參數。
    • emplace_hint:接受一個迭代器作為提示參數,用于提高插入效率,但提示錯誤可能會降低效率。
  • 返回值:
    • insert 和 emplace:返回一個 std::pair<iterator, bool>,表示插入是否成功。
    • emplace_hint:返回一個指向新插入元素或已存在元素的迭代器。
#include <iostream>
#include <unordered_map>int main() {std::unordered_map<int, std::string> myMap;auto result = myMap.insert({1, "one"});if (result.second) {std::cout << "Inserted successfully." << std::endl;} else {std::cout << "Element already exists." << std::endl;}return 0;
}
int main() {std::unordered_map<int, std::string> myMap;auto result = myMap.emplace(2, "two");if (result.second) {std::cout << "Emplaced successfully." << std::endl;} else {std::cout << "Element already exists." << std::endl;}return 0;
}
int main() {std::unordered_map<int, std::string> myMap;auto hint = myMap.begin();auto it = myMap.emplace_hint(hint, 3, "three");std::cout << "Inserted key: " << it->first << ", value: " << it->second << std::endl;return 0;
}

1.4. 參考鏈接

  • C++ STL unordered_map容器用法詳解

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

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

相關文章

在線測試來料公差

UI 上圖 V1 上圖 V2 V3 Code import tkinter as tk from tkinter import messagebox, scrolledtext import socket import threading from datetime import datetime import os import logging from PIL import Image, ImageTk import subprocess# 定義文件夾路徑…

【優秀三方庫研讀】【C++基礎知識】odygrd/quill -- 折疊表達式

compute_encoded_size_and_cache_string_lengths 方法中這段代碼是一個C的折疊表達式&#xff08;fold expression&#xff09;的應用&#xff0c;用于計算多個參數編碼后的總大小。下面我將詳細解釋這段代碼的每個部分&#xff0c;并說明為什么這樣寫。 代碼如下&#xff1a; …

數據庫安裝和升級和雙主配置

備份和導入數據 ./mysqldump -u root -p123321 test > test.sql rsync -av test.sql root192.168.0.212:/usr/local/mysql/ ./mysql -uroot -p test < …/test.sql sudo tar -zxvf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz -C /usr/local/ sudo ln -sfn /usr/loca…

【C語言】條件編譯

&#x1f984;個人主頁:修修修也 &#x1f38f;所屬專欄:C語言 ??操作環境:Visual Studio 2022 目錄 條件編譯 常用的預處理指令 核心應用場景 1.防止頭文件重復包含 2.跨平臺兼容性 3.調試模式與發布模式 4.功能開關 5.代碼兼容性處理 結語 條件編譯 一般情況下,源程序中所有…

如何在安卓平板上下載安裝Google Chrome【輕松安裝】

安卓平板可以通過系統內置的應用商店直接搜索并下載谷歌瀏覽器。用戶打開平板上的“Play 商店”&#xff0c;在搜索框輸入Google Chrome。出現結果后&#xff0c;點擊第一個帶有“Google LLC”字樣的應用圖標&#xff0c;然后點“安裝”按鈕。下載和安裝時間和網速有關&#xf…

.NET代碼保護混淆和軟件許可系統——Eziriz .NET Reactor 7

.NET代碼保護混淆和軟件許可系統——Eziriz .NET Reactor 7 1、簡介2、功能特點3、知識產權保護功能4、強大的許可系統5、軟件開發工具包6、部署方式7、下載 1、簡介 .NET Reactor是用于為.NET Framework編寫的軟件的功能強大的代碼保護和軟件許可系統&#xff0c;并且支持生成…

利用 SSE 實現文字吐字效果:技術與實踐

利用 SSE 實現文字吐字效果:技術與實踐 引言 在現代 Web 應用開發中,實時交互功能愈發重要。例如,在線聊天、實時數據監控、游戲中的實時更新等場景,都需要服務器能夠及時將數據推送給客戶端。傳統的請求 - 響應模式在處理實時性要求較高的場景時顯得力不從心,而 Server…

一個簡單易用的密碼生成器

基于瀏覽器的確定性密碼生成工具&#xff0c;通過用戶輸入的網站名稱和鹽值生成符合安全要求的密碼。特點&#xff1a; ? 相同輸入始終生成相同密碼 ? 密碼自動包含大小寫字母、數字和特殊符號 ? 以字母開頭&#xff0c;固定8位長度 ? 完全在客戶端運行&#xff0c;保護…

水上與水下遙控技術要點對比

1. 水上無人機遙控器技術要點 (1) 控制方式 多通道控制&#xff1a;通常使用2.4GHz或5.8GHz無線電信號&#xff0c;支持多通道&#xff08;如4通道以上&#xff09;分別控制飛行器的姿態&#xff08;俯仰、橫滾、偏航&#xff09;和油門。 高級飛行模式&#xff1a;如定高模…

Android_SDK鏈接 雷神模擬器(端口問題) --- app筆記

調試環境&#xff1a;JDK&#xff08;java&#xff09; SDK&#xff08;android&#xff09; Node.js 雷神模擬器&#xff08;或 真機&#xff09; Appium&#xff08;Appium Server【內外件&#xff08;dos內件、界面化工具&#xff09;】、Appium Inspector&#xff09; p…

FreeRTOS【3】任務調度算法

重要概念 在運行的任務&#xff0c;被稱為"正在使用處理器"&#xff0c;它處于運行狀態。在單處理系統中&#xff0c;任何時間里只能有一個任務處于運行狀態。 非運行狀態的任務&#xff0c;它處于這 3 中狀態之一&#xff1a;阻塞(Blocked)、暫停(Suspended)、就緒…

SLAM常用地圖對比示例

序號地圖類型概述1格柵地圖將現實環境柵格化&#xff0c;每一個柵格用 0 和 1 分別表示空閑和占據狀態&#xff0c;初始化為未知狀態 0.52特征地圖以點、線、面等幾何特征來描繪周圍環境&#xff0c;將采集的信息進行篩選和提取得到關鍵幾何特征3拓撲地圖將重要部分抽象為地圖&…

【Vue】TypeScript與Vue3集成

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;Vue 文章目錄 1. 前言2. 環境準備與基礎搭建2.1. 安裝 Node.js 與 npm/yarn/pnpm2.2. 創建 Vue3 TypeScript 項目2.2.1. 使用 Vue CLI2.2.2. 使用 Vite&#xff08;推薦&#xff09;2.2.3. 目錄結構簡述 3. Vue3 TS 基礎語法整…

高防IP是什么

"高防IP"是指"高防護IP"&#xff0c;是一種防御DDoS&#xff08;分布式拒絕服務攻擊&#xff09;的網絡安全服務。在分布式拒絕服務攻擊中&#xff0c;攻擊者會利用許多不同的計算機或者其他設備&#xff0c;通過向目標發送大量的網絡請求來嘗試使目標服務…

手機訪問電腦端Nginx服務器配置方式

修改當前站點Nginx的配置如下。其中端口號必須是一個比較獨特的端口號&#xff0c;比如8001。這樣可以跟別的項目區分開來。域名使用0.0.0.0。 server {listen 80;listen 8001;server_name zfmap.cc 0.0.0.0;假設你電腦端的ip地址是192.168.1.101,那么你的手機與你的電腦連在同…

【算法】計數排序、桶排序、基數排序

算法系列八&#xff1a;非比較排序 一、計數排序 1.實現 1.1步驟 1.2代碼 2.性質 2.1穩定性 2.1.1從前往后前始版&#xff1a; 2.1.2從后往前末始版&#xff1a; 2.2復雜度 2.2.1時間復雜度 2.2.2空間復雜度 二、桶排序 1.實現 1.1步驟 1.2代碼 2.穩定性 三、…

JDK版本與Spring Boot版本之間對應關系

JDK&#xff08;Java Development Kit&#xff09;版本與Spring Boot版本之間存在一定的對應關系&#xff0c;選擇合適的搭配對項目的穩定性、性能及功能實現至關重要&#xff0c;以下是詳細介紹&#xff1a; 主要版本對應關系 Spring Boot版本發布日期支持的JDK版本備注3.2.…

如何檢測Python項目哪些依賴庫沒有使用

要檢測Python項目中哪些依賴庫未被使用&#xff0c;可以采用以下方法&#xff1a; 1. 使用靜態分析工具 vulture&#xff1a;靜態分析工具&#xff0c;檢測未使用的代碼和導入 pip install vulture vulture your_project/pyflakes&#xff1a;檢查未使用的導入語句 pip ins…

【智能指針】—— 我與C++的不解之緣(三十三)

一、智能指針的使用 還記得&#xff0c;在異常學習的時候&#xff0c;我們分析出了一個問題 double Divide(int x, int y) {if (y 0){throw string("the y is zero");}return (double)x / double(y); } void test(int x, int y) {int* arr new int[10];Divide(x,…

Hadoop+Spark 筆記 2025/4/21

讀書筆記 定義 1. 大數據&#xff08;Big Data&#xff09; - 指傳統數據處理工具難以處理的海量、高速、多樣的數據集合&#xff0c;通常具備3V特性&#xff08;Volume體量大、Velocity速度快、Variety多樣性&#xff09;。擴展后還包括Veracity&#xff08;真實性&#x…