C++ unordered_set unordered_map

上篇文章我們講解了哈希表的實現,這節嘗試使用哈希表來封裝unordered_set/map

1. unordered_set/map的框架

封裝的過程實際上與set/map類似,在unordered_set/map層傳遞一個仿函數,用于取出key值

由于我們平常使用的都是unordered_set/map,因此哈希函數應在unordered_set/map層作為參數傳遞給哈希表

// unordered_set.h
template<typename K>
struct HashFunc
{size_t operator()(const K& key){return (size_t)key;}
};template<>
struct HashFunc<string>
{size_t operator()(const string& s){size_t ans = 0;for (auto& e : s){ans *= 131;ans += e;}return ans;}
};namespace byh
{template<typename K, typename Hash = HashFunc<K>>class unordered_set{struct KeyOfSet{const K& operator()(const K& key){return key;}};public:bool insert(const K& key){return _table.insert(key);}private:hash_bucket::HashTable<K, K, KeyOfSet, Hash> _table;};
}// unordered_map.h
namespace byh
{template<typename K, typename V, typename Hash = HashFunc<K>>class unordered_map{struct KeyOfMap{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:bool insert(const pair<K, V>& kv){return _table.insert(kv);}private:hash_bucket::HashTable<K, pair<K, V>, KeyOfMap, Hash> _table;};
}

2. 迭代器

在unordered_set/map這里,迭代器是對哈希節點指針的封裝

遍歷過程中,如果當前節點的next不為空,則直接迭代到下一節點;如果當前節點的next為空,則迭代到下一個不為空的桶

在這里插入圖片描述

在這里插入圖片描述

因此,迭代器中僅僅有節點的指針還不夠,還要有哈希表;迭代器在構造時將節點的指針和哈希表的指針作為參數傳遞

但由于table在哈希表中是私有成員,迭代器類中不能直接訪問table,這里有兩種解決方法

  1. 將迭代器類聲明為哈希表的友元類
  2. 在哈希表中使用內部類創建迭代器類,內部類天然就是外部類的友元類
// 友元的做法
template<typename K, typename T, typename KeyOfT, typename Hash>
class HashTable;template<typename K, typename T, typename Ref, typename Ptr, typename KeyOfT, typename Hash>
class __Iterator
{using Node = HashNode<T>;using Self = __Iterator<K, T, Ref, Ptr, KeyOfT, Hash>;
public:__Iterator(Node* node, HashTable<K, T, KeyOfT, Hash>* pht):_node(node),_pht(pht){}Self& operator++(){if (_node->_next) _node = _node->_next;else{KeyOfT kot;Hash hash;size_t pos = hash(kot(_node->_data)) % _pht->_table.size();int i = 0;for (i = pos + 1; i < _pht->_table.size(); i++){Node* cur = _pht->_table[i];if (cur){_node = cur;break;}}if(i == _pht->_table.size()) _node = nullptr;}return *this;}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}private:Node* _node;HashTable<K, T, KeyOfT, Hash>* _pht;
};template<typename K, typename T, typename KeyOfT, typename Hash>
class HashTable
{friend __Iterator<K, T, T&, T*, KeyOfT, Hash>;
public:using Node = HashNode<T>;using iterator = __Iterator<K, T, T&, T*, KeyOfT, Hash>;// ......
}
// 內部類的做法
template<typename K, typename T, typename KeyOfT, typename Hash>
class HashTable
{template<typename Ref, typename Ptr>class __Iterator{using Node = HashNode<T>;using Self = __Iterator<Ref, Ptr>;public:__Iterator(Node* node, HashTable* pht):_node(node), _pht(pht){}Self& operator++(){if (_node->_next) _node = _node->_next;else{KeyOfT kot;Hash hash;size_t pos = hash(kot(_node->_data)) % _pht->_table.size();int i = 0;for (i = pos + 1; i < _pht->_table.size(); i++){Node* cur = _pht->_table[i];if (cur){_node = cur;break;}}if (i == _pht->_table.size()) _node = nullptr;}return *this;}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}private:Node* _node;HashTable* _pht;};public:using Node = HashNode<T>;using iterator = __Iterator<T&, T*>;// ......
}

內部類做法的好處時,內部類能直接使用外部類的模板參數,不用向友元方式那樣傳遞很多模板參數,同時內部類能直接使用外部類而不用傳遞模板參數

哈希表的迭代器一旦設計好,unordered_set/map層無非就是封裝,這里不再敘述

3. const迭代器

const迭代器的整體思路沒難度,但有些細節地方需要注意

在哈希表層和unordered_set/map層添加完const迭代器后

在這里插入圖片描述

template<typename K, typename T, typename KeyOfT, typename Hash>
class HashTable
{template<typename Ref, typename Ptr>class __Iterator{using Node = HashNode<T>;using Self = __Iterator<Ref, Ptr>;public:__Iterator(Node* node, const HashTable* pht):_node(node), _pht(pht){}// ......private:Node* _node;const HashTable* _pht;};

關于unordered_map的operator[],其設計思路與set/map相同

unordered_set/map層的插入、刪除、查找操作也同樣是簡單的封裝

4. 測試

void Print(const unordered_set<int>& s)
{unordered_set<int>::const_iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;
}void Test_unordered_set()
{vector<int> v = { 1, 4, 2, 3, 5, 9, 11 };unordered_set<int> s;for (auto& e : v) s.insert(e);cout << "const迭代器: ";Print(s);cout << s.find(4) << endl;cout << s.find(54) << endl;s.erase(4);cout << s.find(4) << endl;
}

在這里插入圖片描述

void Test_unordered_map()
{unordered_map<string, int> m;vector<string> v = { "apple", "apple", "banana", "watermelon", "banana" };for (auto& e : v) m[e] ++;unordered_map<string, int>::iterator it = m.begin();while (it != m.end()){cout << it->first << " " << it->second << endl;++it;}cout << endl;cout << m.find("apple") << endl;cout << m.find("abdsaf") << endl;m.erase("apple");cout << m.find("apple") << endl;
}

在這里插入圖片描述

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

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

相關文章

REST API、FastAPI與Flask API的對比分析

以下是關于REST API、FastAPI與Flask API的對比分析&#xff0c;涵蓋架構設計、性能表現、開發效率等核心維度&#xff1a; 一、核心定位與架構差異 REST API 本質&#xff1a;一種基于HTTP協議的架構風格&#xff0c;強調資源化操作&#xff08;通過URI定位資源&#xff09;、…

實戰交易策略 篇二十二:情緒流龍頭交易策略

文章目錄 系列文章理論基礎股市的本質資金與情緒題材龍頭股龍頭戰法實戰技法情緒流技術分析擇時實操情緒流龍頭戰法要訣六大步驟九大術法買賣點量化標準系列文章 實戰交易策略 篇一:奧利弗瓦萊士短線交易策略 實戰交易策略 篇二:杰西利弗莫爾股票大作手操盤術策略 實戰交易策…

用VNA進行天線阻抗匹配的實例大圖

比如我這天線&#xff0c;在7Mhz時不諧振&#xff0c;我進行匹配 天線的阻抗很高&#xff0c;大約是在500-1400歐&#xff0c;而等效電容電感很小。 所以我考慮使用阻抗變壓器降低阻抗。 1。測試天線阻抗&#xff0c;電阻相當高&#xff0c;等效電容很小。 2。通過磁環匹配到…

一個讀寫excel的簡單程序(golang)

最近總有一些臨時統計的需求&#xff0c;比如其他團隊生產的一批數據&#xff0c;需要確認這批數據是否入到數倉&#xff0c;提供的列表就是一個excel&#xff0c;我們就需要讀取excel中的所有數據&#xff0c;之后查詢數倉數據庫確認這批數據是否存在&#xff0c;并分別將存在…

【AI面試準備】AI誤判案例知識庫優化方案

面試題&#xff1a;建立內部知識庫&#xff1a;收集AI誤判案例訓練領域專屬模型。 在回答關于“建立內部知識庫收集AI誤判案例訓練領域專屬模型”的面試問題時&#xff0c;建議從以下結構化框架展開&#xff0c;既能體現專業性&#xff0c;又能展現解決問題的系統性和實際落地…

Ocelot\Consul\.NetCore的微服務應用案例

案例資料鏈接&#xff1a;https://download.csdn.net/download/ly1h1/90733765 1.效果 實現兩個微服務ServerAPI1和ServerAPI2的負載均衡以及高可用。具體原理&#xff0c;看以下示意圖。 2.部署條件 1、騰訊云的輕量化服務器 2、WindowServer2016 3、.NETCore7.0 4、Negut …

中小企業MES系統需求文檔

適用對象&#xff1a;中小型離散制造企業&#xff08;年產值1-5億&#xff0c;員工200-800人&#xff09; 版本&#xff1a;V1.0 日期&#xff1a;2025年5月2日 一、業務背景與目標 1.1 現狀痛點 生產黑箱化&#xff1a;車間進度依賴人工匯報&#xff0c;異常響應延遲>2小…

OpenAI最新發布的GPT-4.1系列模型,性能體驗如何?

簡單來說,這次GPT-4.1的核心思路就是:更實用、更懂開發者、更便宜!OpenAI這次沒搞太多花里胡哨的概念,而是實實在在地提升了大家最關心的幾個點:寫代碼、聽指令、處理超長文本,而且知識庫也更新到了2024年6月。 寫代碼。要說這次GPT-4.1最亮眼的地方,可能就是寫代碼這塊…

【基礎算法】二分查找的多種寫法

前言 在算法競賽中&#xff0c;二分查找使用的頻率是非常高的&#xff0c;對于C選手而言&#xff0c;有STL中自帶的lower_bound和upper_bound二分查找&#xff0c;可以很方便的進行二分查找。但是非C選手、或者需要自定義多條件查找的情況需要自己寫一個二分&#xff0c;本文對…

蘭亭妙微:火箭發射界面案例分享

北京藍藍設計團隊來自清華美院&#xff0c;工作多年&#xff0c;行業經驗豐富&#xff0c;專業性很強。我們是熱愛設計&#xff0c;設計不僅是我們的專業&#xff0c;我們的職業&#xff0c;還是我們的愛好。每一個藍藍設計的設計師都希望自己的設計越來越好&#xff0c;以高標…

完美解決.NET Framework 4.0 中 System.Drawing 庫不支持 WebP 格式的圖像處理

如果你想在 .NET Framework 4.0 中使用 ImageMagick 處理圖片&#xff0c;可以通過 Magick.NET 庫來實現。Magick.NET 是 ImageMagick 的 .NET 封裝&#xff0c;可以用來讀取、寫入、編輯圖像。 以下是如何使用 Magick.NET 來處理圖像并提取圖像的寬度和高度。 步驟&#xff…

string--OJ1

鏈接: 例一 鏈接: 例er class Solution { public:int myAtoi(string str) {int sign 1;int ret0;int i0;while(str[i] ){i;}if(str[i]||str[i]-){if(str[i]-)sign*-1;i;}while(str[i]>0&&str[i]<9){int rstr[i] - 0;if(ret>INT_MAX/10||(retINT_MAX/10&…

Go 寫一個簡單的Get和Post請求服務

Go 寫一個簡單的Get和Post請求服務 ? 一、準備工作 安裝 Go 官網下載地址 安裝后執行&#xff1a; go version安裝 VS Code 插件 在 VS Code 插件市場搜索并安裝插件&#xff1a;Go&#xff08;由 Go 團隊提供&#xff09; 配置環境變量&#xff08;可選&#xff09; 設置 …

哪些因素會影響遠程視頻監控的質量?淺述EasyCVR視頻智能診斷技術

在安防領域&#xff0c;無線監控系統憑借其靈活部署、便捷擴展的特性得到廣泛應用。然而&#xff0c;實時監控圖像清晰度不足、回放調查受限等問題&#xff0c;嚴重制約了其應用效果。經分析&#xff0c;攝像機性能、線纜質量、無線網橋性能、交換機配置及供電電壓等是影響圖像…

Java大師成長計劃之第10天:鎖與原子操作

&#x1f4e2; 友情提示&#xff1a; 本文由銀河易創AI&#xff08;https://ai.eaigx.com&#xff09;平臺gpt-4o-mini模型輔助創作完成&#xff0c;旨在提供靈感參考與技術分享&#xff0c;文中關鍵數據、代碼與結論建議通過官方渠道驗證。 在多線程編程中&#xff0c;鎖與原子…

線性代數——行列式?

目錄 一、行列式的定義? 1-1、三階行列式練習 1-2、下面介紹下三角行列式、上三角行列式、對角行列式 ?編輯 二、行列式的性質 2-1、性質1&#xff0c;2&#xff0c;3&#xff0c;4&#xff0c;5&#xff0c;6 ?編輯 2-2、性質7 2- 3、拉普拉斯定理、克萊姆法則 三…

微軟推出數款Phi 4“開放式”人工智能模型

微軟周三推出了幾款新的“開放式”人工智能模型&#xff0c;其中功能最強大的模型至少在一個基準測試上可與 OpenAI 的 o3-mini 相媲美。所有新的授權模型——Phi 4 mini reasoning、Phi 4 reasoning 和 Phi 4 reasoning plus——都是“推理”模型&#xff0c;這意味著它們能夠…

VPN訪問SAP組服務器報登陸負載均衡錯誤88:無法連接到消息服務器(RC=9)

用戶反饋用SAPGUI接入SAP時報錯&#xff1a;登陸負載均衡錯誤88&#xff1a;無法連接到消息服務器(RC9) 經了解是通過VPN訪問&#xff0c;但VPN沒有放行ICMP訪問&#xff0c;導致不能PING通&#xff0c;不能確認是網絡問題還是什么問題。 解決方案&#xff1a; 1、VPN由原&am…

使用AI-01開發板和開源后端服務搭建整套小智服務系統

使用AI-01開發板和開源后端服務搭建整套小智服務系統 四博智聯的AI-01開發板&#xff0c;基于樂鑫ESP32-C2 專屬定制的離線語音模組&#xff0c;能夠完美的接入小智AI服務平臺&#xff0c;再使用開源后端服務&#xff0c;就能夠搭建一個完整的小智AI服務系統了。 下面是具體…

字節跳動在GitHub上有哪些開源項目

字節跳動&#xff08;ByteDance&#xff09;在GitHub上開源了許多項目&#xff0c;涵蓋前端、后端、云原生、AI、數據庫等多個領域。以下是一些典型項目及其簡介&#xff1a; 1. 前端 & 跨平臺開發 Hippy 倉庫: Tencent/Hippy&#xff08;注&#xff1a;Hippy 最初由騰訊開…