開散列哈希桶

通過上面這幅圖,讀者應該能較為直觀地理解何為開散列,以及閉散列與開散列的區別在哪里 —— 數據的存儲形式不同,至于其他的,如確定每個元素的哈希地址等一概相同。

與閉散列相比,開散列能夠更好地處理發生沖突的元素 —— 假使我們要在上述閉散列中再插入 5 ,會因為 24 的先插入而導致 5 必須往后尋找空位置,進而影響 6 的插入等。

1. 什么是桶?

通過 HashFunc 計算每個元素的哈希地址,哈希地址相同的元素所組成的子集稱為 哈希桶 ,這些元素通過單鏈表鏈接在一起。

如:4 % 10 == 24 % 10 == 34 % 10 == 44 % 10 == 4

開散列的每個桶中存的都是發生哈希沖突的元素。

2. 開散列框架搭建
  • HashFunc
template<class K>
struct HashFunc
{size_t operator()(const K& key){size_t ret = key;return ret;}
};// 為 string 寫一個特化版本
template<>
struct HashFunc<string>
{size_t operator()(const string& s){size_t hash = 0;for (auto& e : s){hash = hash * 131 + e; // 131 是前輩用大量數據測試得到的值,可以盡大程度避免哈希沖突}return hash;}
};
  • HashNode
	template<class K, class V>struct HashNode{HashNode* _next;pair<K, V> _kv;HashNode(const pair<K, V>& kv):_next(nullptr),_kv(kv){}};
  • HashTable
	template<class K, class V, class Hash = HashFunc<K>>class HashTable{typedef HashNode<K, V> Node;public:HashTable(){_tables.resize(10);}private:vector<Node*> _tables;size_t _n = 0;};
3. Insert()
	bool Insert(const pair<K, V>& kv){if (Find(kv.first)) // 未實現的 Find,已存在則返回該元素哈希位置的指針,不存在則返回空return false;Hash hs;// 擴容 if (_n == _tables.size()) // STL 庫中,開散列的負載因子設為 1{// ...}// 插入size_t hashi = hs(kv.first) % _tables.size();Node* newNode = new Node(kv);newNode->_next = _tables[hashi];_tables[hashi] = newNode;// 頭插++_n;return true;}

再來聊一聊擴容邏輯。

與閉散列不同,我們不準備復用 Insert() 完成數據的拷貝 —— 假設哈希桶中已經存在 1000, 000 個元素,需要重新拷貝 1000, 000 個元素,再將原表中的元素一一釋放。

更好的辦法是,直接將原表中的節點 掛到 新表對應的哈希位置上

	// 擴容部分if (_n == _tables.size()){vector<Node*> newTable(2 * _tables.size(), nullptr);for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;size_t hashi = hs(cur->_kv.first) % newTable.size();cur->_next = newTable[hashi];newTable[hashi] = cur;cur = next;}_tables[i] = nullptr;// 將原表置空}_tables.swap(newTable);// 不需要手動將 newTable delete[],編譯器會自動調用 vector 的析構函數,// 且 swap 后,newTable 里全為空,不需要擔心內存泄露的問題}
4. Find()Erase()
  • Find()
	Node* Find(const K& key){Hash hs;size_t hashi = hs(key) % _tables.size();Node* cur = _tables[hashi];while (cur){if (cur->_kv.first == key){break;}cur = cur->_next;}if (cur && cur->_kv.first == key)return cur;else return nullptr;}
  • Erase()

開散列的 Erase() 不能像閉散列那樣,Find() 后直接刪除。

調用 Find() 能得到 key 對應的 HashData 的指針,但無法得到前一個節點的指針,會造成一系列問題。

	bool Erase(const K& key){Hash hs;size_t hashi = hs(key) % _tables.size();Node* cur = _tables[hashi];Node* prev = nullptr; // prev 為前一個節點指針while (cur){if (cur->_kv.fisrt == key) // 找到了{if (prev) // prev 不為空,說明 cur 為中間節點{prev->_next = cur->_next;}else // prev 為空,說明 cur 為 _tables[hashi]{_tables[hashi] = cur->_next;}delete cur;--_n;return true;}prev = cur;cur = cur->_next;}return false;}

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

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

相關文章

Taro + React + Tailwind 開發微信小程序問題匯總(持續更新中...)

搞小程序也有兩周了&#xff0c;踩了很多坑&#xff0c;有些問題很難搜索到&#xff0c;在這里記錄一下問題和自己的解決方案&#xff0c;希望能幫助到需要的小伙伴&#xff5e; 1. 真機調試報錯&#xff1a;Error: module ‘babel/runtime/helpers/Arrayincludes.js’ is not …

Transformers 加速的一些常用技巧

Transformers 是一個強大的架構&#xff0c;但模型因其采用的自注意力機制&#xff0c;雖然能夠有效地處理序列數據并捕獲長距離依賴關系&#xff0c;但同時也容易導致在訓練過程中出現OOM&#xff08;Out of Memory&#xff0c;內存不足&#xff09;或者達到GPU的運行時限制。…

AI大模型探索之路-訓練篇22: ChatGLM3微調實戰-從原理到應用的LoRA技術全解

系列篇章&#x1f4a5; AI大模型探索之路-訓練篇1&#xff1a;大語言模型微調基礎認知 AI大模型探索之路-訓練篇2&#xff1a;大語言模型預訓練基礎認知 AI大模型探索之路-訓練篇3&#xff1a;大語言模型全景解讀 AI大模型探索之路-訓練篇4&#xff1a;大語言模型訓練數據集概…

MPLAB X IDE編譯attiny1616工程報錯卻無報錯信息

MPLAB X IDE(XC-8編譯器)編譯報錯&#xff0c;無具體錯誤內容&#xff0c;僅顯示需要xc-8 pro的警告。 內存占用率顯示為81%&#xff0c;未超標。 原因&#xff1a;軟件使用了microchip的bootloader功能。應用程序起始地址&#xff08;也是bootloader結束地址&#xff09;設置錯…

社交巨頭:探索Facebook的震撼力量

Facebook作為社交媒體領域的巨頭&#xff0c;不僅在數字化社會中占據著重要地位&#xff0c;更是影響了人們的生活、工作和社交方式。本文將深入探索Facebook的震撼力量&#xff0c;從多個角度解讀其在當今社會中的重要性和影響。 1. 全球用戶覆蓋的壯觀規模 Facebook作為全球…

軟件定義汽車七大典型應用場景

隨著軟件定義汽車典型應用場景的落地&#xff0c;用戶將明顯體驗到汽車從交通工具向智能移動終端的轉變。幾十年前主要用高性能的底盤操穩與動力系統定義一臺好車&#xff0c;幾年前主要用智能化系統與智能交互滿足終端用戶的用車體驗&#xff0c;未來將調度全車傳感器與數據驅…

c 數組遍歷

#include <stdio.h> #include <stdlib.h> int main() { printf(“指針數組練習&#xff01;&#xff01;&#xff01;\n”); /* 數組名就是數組的首地址 數組存在一段連續的內存空間中 */ double score[] {60, 70, 80, 90, 100}; double *ptr_score; i…

docker安裝時報錯:Error: Nothing to do

安裝docker時報以下錯誤 解決方法&#xff1a; 1.下載關于docker的相關依賴環境 yum -y install yum-utils device-mapper-persistent-data lvm22.設置下載Docker的鏡像源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo3…

FMEA存在的五個主要不足及改進措施——FMEA軟件

免費試用FMEA軟件-免費版-SunFMEA 在制造業和產品設計領域&#xff0c;失效模式與影響分析&#xff08;Failure Modes and Effects Analysis&#xff0c;簡稱FMEA&#xff09;被廣泛運用&#xff0c;用于預防潛在的設計或制造缺陷。然而&#xff0c;盡管FMEA在風險管理方面發揮…

開發者集結號:大灣區 Open Source Day 邀您共探技術前沿

開源技術正以其開放、協作的特性&#xff0c;引領著軟件開發的新潮流&#xff0c;是推動社會進步的重要力量。作為開發者&#xff0c;您是否渴望深入了解開源項目的前沿動態&#xff1f;由ALC深圳與2024中國互聯網發展創新與投資大賽聯合舉辦、FISCO金鏈盟深度參與的大灣區 Ope…

MySQL————創建存儲過程函數

存儲過程使用大綱 有參數傳遞 delimiter $$ 聲明一個名稱為get_student_introduce create procedure add_student_infor( in p_userName VARCHAR(20),in p_phone VARCHAR(11),in p_sex char(2),in p_introduce VARCHAR(255)) 開始操作 BEGIN 撰寫真正在操作DMLDQL都行 INSE…

CSS---復合選擇器、元素顯示模式和背景(三)

一、CSS的復合選擇器 1.1 什么是復合選擇器 在CSS中&#xff0c;可以根據選擇器的類型把選擇器分為基礎選擇器和復合選擇器&#xff0c;復合選擇器是建立在基礎選擇器之上&#xff0c;對基本選擇器進行組合形成的。 復合選擇器是由兩個或多個基礎選擇器連寫組成&#xff0c;它…

SpringBoot3和SpringBoot2分別整合knife4j(openApi)

文章目錄 一、SpringBoot2進行整合knife4j1.1 導入依賴1.2 配置knife4j 配置文件1.3 可以在接口上配置 注解進行信息的配置 二、SpringBoot3 整合kinfe4j(openApi)2.1 導入依賴2.2 yaml配置文件2.3 swagger初始化配置2.4 創建接口 一、SpringBoot2進行整合knife4j 1.1 導入依賴…

【云原生】kubernetes核心組件

引言&#xff1a; Kubernetes 是為運行分布式集群而建立的&#xff0c;分布式系統的本質使得網絡成為 Kubernetes 的核心和必要組成部分&#xff0c;了解 Kubernetes 網絡模型可以使你能夠正確運行、監控和排查應用程序故障。 一、Kubernetes的核心組件 1.1、Master組件 1.1.…

基于Springboot+Vue的Java項目-農產品直賣平臺系統開發實戰(附演示視頻+源碼+LW)

大家好&#xff01;我是程序員一帆&#xff0c;感謝您閱讀本文&#xff0c;歡迎一鍵三連哦。 &#x1f49e;當前專欄&#xff1a;Java畢業設計 精彩專欄推薦&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python畢業設計 &am…

Kubernetes之Headless Services

Kubernetes中的Headless Services&#xff08;無頭服務&#xff09;是一種特殊類型的服務&#xff08;Service&#xff09;定義&#xff0c;它不提供傳統意義上的負載均衡和集群IP地址分配。在無頭服務中&#xff0c;spec.clusterIP 字段被顯式設置為None &#xff0c;Kubernet…

可道云teamOS企業網盤實用插件介紹:實時在線流程圖編輯與分享,用在線流程圖打造數字化工作流程

在使用企業網盤用于日常辦公的情況下&#xff0c;有一些實用的在線小工具能為團隊效率和協作帶來一定的提升。 今天要給大家介紹的可道云teamOS的在線畫流程圖&#xff0c;是很值得介紹的一個在線工具。 在線流程圖&#xff1a;直觀展示&#xff0c;高效便捷 以往我們想要梳理…

FANUC機器人單軸零點標定時提示無法執行零點標定,由于重力補償已啟用,所有機器人軸的脈沖計數必須有效

FANUC機器人單軸零點標定時提示無法執行零點標定,由于重力補償已啟用,所有機器人軸的脈沖計數必須有效 首先,機器人由于長時間斷電未使用,6個軸的編碼器數據全部丟失,上電后報警SRVO-062, 有關SRVO-062故障報警的相關內容可參考以下鏈接: FANUC機器人SRVO-062報警原因分…

LeetCode 2391. 收集垃圾的最少總時間

Problem: 2391. 收集垃圾的最少總時間 問題分解 我們將這個問題分解為以下幾個小問題&#xff1a; 計算每種垃圾&#xff08;金屬、紙、玻璃&#xff09;在每個房子中的數量。確定每種垃圾車最后到達的房子。計算每種垃圾車行駛的總時間。計算每種垃圾車收拾垃圾的總時間。返…