【C++高階】高效數據存儲:理解并模擬實現紅黑樹Map與Set

📝個人主頁🌹:Eternity._
?收錄專欄?:C++ “ 登神長階 ”
🤡往期回顧🤡:了解 紅黑樹
🌹🌹期待您的關注 🌹🌹

在這里插入圖片描述

在這里插入圖片描述
在這里插入圖片描述

?模擬實現Map與Set

  • 📒1. 改造紅黑樹
  • 📜2. 紅黑樹的迭代器
    • 🌞迭代器基本設計
    • 🌙begin()與end()
    • ?operator++()與operator--()
  • 📚3. Set的模擬實現
    • 🧩Set的基本設計
  • 📝4. Map的模擬實現
    • 🧩Map的基本設計
  • 📖5. 總結


前言: 在編程的浩瀚宇宙中,數據結構作為構建程序的基石,扮演著至關重要的角色。它們不僅定義了數據的存儲方式,還極大地影響著程序的性能與效率。在眾多經典數據結構中,Map(映射)和Set(集合)以其獨特的性質和廣泛的應用場景,成為了程序員們手中不可或缺的工具。Map允許我們根據鍵(Key)快速檢索值(Value),而Set則提供了一種不包含重復元素的數據集合

深入理解并熟練掌握這些高級數據結構,并非一蹴而就。為了更加深刻地認識Map與Set的工作原理,以及它們背后隱藏的算法智慧,一個行之有效的方法便是親手模擬實現它們。這一過程,不僅能夠幫助我們加深對數據結構的理解,還能在實踐中鍛煉編程能力和問題解決能力

本文旨在為讀者提供一個全面而深入的視角,通過逐步解析紅黑樹的基本原理、詳細闡述模擬實現的過程,并輔以豐富的代碼示例,幫助讀者掌握紅黑樹Map與Set的構建與使用。我們將從最基本的二叉搜索樹出發,逐步引入紅黑樹的特性和規則

讓我們一起踏上學習的旅程,探索它帶來的無盡可能!


📒1. 改造紅黑樹

改造紅黑樹以適配map和set容器,主要涉及到如何根據這兩種容器的特性來設計和實現紅黑樹節點的存儲以及相應的操作。map和set的主要區別在于它們存儲的元素類型:map存儲鍵值對(key-value pairs),而set僅存儲唯一的鍵值(通常是鍵本身作為值)。盡管如此,它們在底層數據結構(如紅黑樹)的實現上有很多相似之處

改造內容:

  • K:key的類型
  • T:如果是map,則為pair<K, V>; 如果是set,則為K
  • KeyOfT:通過T來獲取key的一個仿函數類
// Map 與 Set
// set -> RBTree<K, K, SetKeyOfT> _t;
// map -> RBTree<K, pair<const K, V, MapKeyOfT>> _t;

紅黑樹的節點設計:

enum Color
{RED,BLACK
};template<class T>
struct RBTreeNode
{RBTreeNode<T>* _left;RBTreeNode<T>* _right;RBTreeNode<T>* _parent;// pair<K, V> _kv; // 上節內容使用的這種方式T _data;Color _col;RBTreeNode(const T& data):_left(nullptr), _right(nullptr), _parent(nullptr), _data(data), _col(RED){}
};

紅黑樹類的實現參考上一篇文章:紅黑樹類的實現
與紅黑樹類的不同的是Insert(插入)的類型是pair<iterator, bool>或者pair<Node*, bool>,然后還要修改內部的return返回的對象
在這里插入圖片描述

在這里插入圖片描述

以pair<Node*, bool>為例
代碼示例:

pair<Node*, bool> Insert(const T& data){if (_root == nullptr){_root = new Node(data);_root->_col = BLACK;return make_pair(_root, true);}Node* parent = nullptr;Node* cur = _root;// 通過仿函數KeyOfT來比較數據的大小KeyOfT kot;while (cur){parent = cur;if (kot(cur->_data) < kot(data)){cur = cur->_right;}else if (kot(cur->_data) > kot(data)){cur = cur->_left;}else{return make_pair(cur, false);}}// 新增節點給紅色cur = new Node(data);// 注意,這里需要保存一個新增節點,以便用來返回Node* newnode = cur;cur->_col = RED;// 旋轉變色return make_pair(newnode, true);;}

對于set,你可以簡單地使用RBTree<K, K, SetKeyOfT>;而對于map,則使用RBTree<K, pair<const K, V>, MapKeyOfT>


📜2. 紅黑樹的迭代器

🌞迭代器基本設計

// 通過模板來達到const的迭代器的復用
template<class T, class Ref, class Ptr>
struct __TreeIterator
{typedef RBTreeNode<T> Node;typedef __TreeIterator<T, Ref, Ptr> Self;Node* _node;// 構造函數__TreeIterator(Node* node):_node(node){}Ref operator*(){return _node->_data;}Ptr operator->(){return &(_node->_data);}bool operator!=(const Self& s){return _node != s._node;}
};

🌙begin()與end()

STL明確規定,begin()與end()代表的是一段前閉后開的區間,而對紅黑樹進行中序遍歷后,
可以得到一個有序的序列,因此:begin()可以放在紅黑樹中最小節點(即最左側節點)的位
置,end()放在最大節點(最右側節點)的下一個位置,關鍵是最大節點的下一個位置在哪塊?
能否給成nullptr呢?答案是行不通的,因為對end()位置的迭代器進行–操作,必須要能找最
后一個元素,此處就不行,因此最好的方式是將end()放在頭結點的位置

在這里插入圖片描述
代碼示例(C++):
(注意:此步需要在RBTree類的內部實現),以便map,set的使用

typedef __TreeIterator<T, T&, T*> iterator;
typedef __TreeIterator<T, const T&, const T*> const_iterator;iterator begin()
{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return iterator(cur);
}iterator end()
{return iterator(nullptr);
}const_iterator begin() const
{Node* cur = _root;while (cur && cur->_left){cur = cur->_left;}return const_iterator(cur);
}const_iterator end() const
{return const_iterator(nullptr);
}

?operator++()與operator–()

operator++()

  • 右不為空,右子樹的最左節點
  • 右為空,沿著到根的路徑找孩子是父親左的那個祖先

operator–()

  • 左不為空,左子樹的最右節點
  • 左為空,沿著到根的路徑找孩子是父親右的那個祖先

注意:++和–正好是完全相反的


代碼示例(C++):

Self& operator++()
{if (_node->_right){Node* cur = _node->_right;while (cur->_left){cur = cur->_left;}_node = cur;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = cur->_parent;}_node = parent;}return *this;
}Self& operator--()
{if (_node->_left){Node* cur = _node->_left;while (cur->_right){cur = cur->_right;}_node = cur;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent&& cur == parent->_left){cur = parent;parent = cur->_parent;}_node = parent;}return *this;
}

📚3. Set的模擬實現

🧩Set的基本設計

template<class K>
class set
{
public:// SetKeyOfT:通過T來獲取key的一個仿函數類struct SetKeyOfT{const K& operator()(const K& key){return key;}};// typename告訴編譯器這是類型,// 因為set不能夠進行修改,所以我們用const迭代器來初始化普通迭代器,來達到不能修改的目的typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;iterator begin() const{return _t.begin();}iterator end() const{return _t.end();}// 復用RBTree中的插入pair<iterator, bool> insert(const K& key){return _t.Insert(key);}private:RBTree<K, K, SetKeyOfT> _t;
};

📝4. Map的模擬實現

🧩Map的基本設計

template<class K, class V>
class map
{
public:// MapKeyOfT:通過pair來獲取kv.first的一個仿函數類struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};// map是一個key不能修改,value能夠修改的結構typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator const_iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}// 重載map中的operatorp[]// operatorp[] 當原數據中沒有時,插入并初始化,有則修改secondV& operator[](const K& key){// 沒有是插入,有則是查找pair<iterator, bool> ret = insert(make_pair(key, V()));return ret.first->second;}// 復用RBTree中的插入pair<iterator, bool> insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};

📖5. 總結

隨著我們對紅黑樹Map與Set的深入探索與模擬實現,這場高效數據存儲的旅程也即將畫上圓滿的句號。回望這段旅程,我們從紅黑樹的基本概念出發,逐步揭示了其保持平衡、實現高效操作的秘密,并通過親手編寫代碼,將理論轉化為了實踐

同時,我們也要意識到,數據結構的選擇并非一成不變。在實際應用中,我們需要根據具體需求、數據規模、性能要求等因素綜合考慮,選擇最合適的數據結構來解決問題。只有這樣,我們才能真正做到高效、穩定地處理數據。

然而,學習之路永無止境。紅黑樹只是眾多高效數據結構中的一種,它們各自有著獨特的優勢和適用場景。在未來的學習與實踐中,我們還需要繼續探索其他數據結構,如AVL樹、B樹、B+樹等,以拓寬我們的視野,提升我們的技能

希望各位在未來的學習與工作中,保持對知識的渴望與追求,勇于挑戰自我,不斷探索未知領域。相信在不久的將來,你們定能在數據處理的廣闊舞臺上大放異彩

在這里插入圖片描述

希望本文能夠為你提供有益的參考和啟示,讓我們一起在編程的道路上不斷前行!
謝謝大家支持本篇到這里就結束了,祝大家天天開心!

在這里插入圖片描述

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

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

相關文章

js ES6 part1

聽了介紹感覺就是把js在oop的使用 作用域 作用域&#xff08;scope&#xff09;規定了變量能夠被訪問的“范圍”&#xff0c;離開了這個“范圍”變量便不能被訪問&#xff0c; 作用域分為&#xff1a; 局部作用域、 全局作用域 1. 函數作用域&#xff1a; 在函數內部聲明的…

爬取天氣數據,利用Pyecharts作輪播圖

爬取網站鏈接&#xff1a;https://lishi.tianqi.com/xiamen/202312.html 爬取了廈門市2023年一整年的天氣數據&#xff0c;包括最高溫&#xff0c;最低溫&#xff0c;天氣&#xff0c;風力風向等 爬蟲代碼&#xff1a; import requests import pandas as pd import csv from…

UML建模案例分析-時序圖和類圖的對應關系

概念 簡單地說&#xff0c;類圖定義了系統中的對象&#xff0c;時序圖定義了對象之間的交互。 例子 一個電子商務系統&#xff0c;會員可通過電子商務系統購買零件。具體功能需求如下&#xff1a; 會員請求結賬時&#xff0c;系統驗證會員的賬戶是否處于登錄狀態&#xff1…

極狐GitLab 17.0 重磅發布,100+ DevSecOps功能更新來啦~【三】

GitLab 是一個全球知名的一體化 DevOps 平臺&#xff0c;很多人都通過私有化部署 GitLab 來進行源代碼托管。極狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中國的發行版&#xff0c;專門為中國程序員服務。可以一鍵式部署…

【基礎篇】1.8 C語言基礎(二)

2.9 預處理指令和宏定義 在STM32開發中,預處理和宏定義常用于配置硬件參數、啟用或禁用特定功能、以及優化代碼以適應不同的硬件配置或應用場景。通過合理地使用預處理和宏定義,我們可以編寫更加靈活、可配置和高效的代碼。 預處理指令如#include、#define等在C語言編程中起…

防火墻圖形化界面策略和用戶認證(華為)

目錄 策略概要認證概要實驗拓撲圖題目要求一要求二要求三要求四要求五要求六 策略概要 安全策略概要&#xff1a; 安全策略&#xff08;Security Policy&#xff09;在安全領域具有雙重含義。宏觀上&#xff0c;安全策略指的是一個組織為保證其信息安全而建立的一套安全需求、…

uniapp 微信小程序接入MQTT

MQTT安裝 前期準備 由于微信小程序需要wss&#xff0c;所以要有域名SSL證書 新建目錄/srv/mosquitto/config&#xff0c;/srv/mosquitto/config/cert 目錄/srv/mosquitto/config中新建配置文件mosquitto.conf&#xff0c;文件內容 persistence true persistence_location /m…

深入探索Apache Flink:流處理的藝術與實踐

在當今的大數據時代&#xff0c;流處理已成為處理實時數據的關鍵技術。Apache Flink&#xff0c;作為一個開源的流處理框架&#xff0c;以其高吞吐量、低延遲和精確一次&#xff08;exactly-once&#xff09;的語義處理能力&#xff0c;在眾多流處理框架中脫穎而出。本文將深入…

在樹莓派設備上導出系統鏡像

鏡像導出 前提條件&#xff1a; 已獲取可以正常使用的設備。已獲取鼠標、鍵盤和電源適配器。已將設備接入可正常使用的網絡。 操作步驟&#xff1a; 連接適配器給設備上電&#xff0c;正常啟動設備&#xff0c;連接鼠標和鍵盤。在終端命令窗格執行如下命令&#xff0c;安裝…

數據模型-ER圖在數據模型設計中的應用

ER圖在數據模型設計中的應用 1. ER圖概述&#xff1a;起源與發展? 實體-關系圖&#xff08;Entity Relationship Diagram&#xff0c;簡稱ER圖&#xff09;起源于1970年代&#xff0c;由Peter Chen首次提出&#xff0c;作為描述數據和信息間關系的圖形化語言。隨著數據庫技術…

[PM]流程與結構設計

流程圖 流程就是為了達到特定目標, 進行的一系列有邏輯性的操作步驟, 由兩個及已上的步驟, 完成一個完整的行為過程, 即可稱為流程, 流程圖就是對這個過程的圖形化展示 分類 業務流程圖 概念: 描述業務流程的一種圖, 通過特定符號和連線表示具體某個業務的處理步驟和過程作…

MyBatis與JDBC相比,有哪些優勢

MyBatis與JDBC&#xff08;Java Database Connectivity&#xff09;相比&#xff0c;在多個方面展現出顯著的優勢。這些優勢使得MyBatis在現代軟件開發中成為一個非常受歡迎的選擇&#xff0c;特別是在處理數據庫交互時。以下是MyBatis相比JDBC的主要優勢&#xff1a; 1. 簡化…

極狐GitLab亮相世界人工智能大會,開啟開源大模型賦能軟件研發新時代

GitLab 是一個全球知名的一體化 DevOps 平臺&#xff0c;很多人都通過私有化部署 GitLab 來進行源代碼托管。極狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中國的發行版&#xff0c;專門為中國程序員服務。可以一鍵式部署…

285個地級市-胡煥庸線數據

全國285個地級市-胡煥庸線數據.zip資源-CSDN文庫 胡煥庸線&#xff1a;中國人口與生態的分界線 胡煥庸線&#xff0c;一條在中國地理學界具有劃時代意義的分界線&#xff0c;由著名地理學家胡煥庸于1935年提出。這條線從黑龍江省的璦琿&#xff08;現黑河市&#xff09;延伸至…

json-server總結

Json-server 是一個專門用于模擬 RESTful API 的工具&#xff0c;它允許前端開發人員在不依賴后端 API 的情況下進行開發&#xff0c;通過本地搭建一個 JSON 服務來快速生成 REST API 風格的后端服務。 一、主要特點與功能 快速搭建&#xff1a;Json-server 使用 JSON 文件作…

HippoRAG如何從大腦獲取線索以改進LLM檢索

知識存儲和檢索正在成為大型語言模型(LLM)應用的重要組成部分。雖然檢索增強生成(RAG)在該領域取得了巨大進步&#xff0c;但一些局限性仍然沒有克服。 俄亥俄州立大學和斯坦福大學的研究團隊推出了HippoRAG&#xff0c;這是一種創新性的檢索框架&#xff0c;其設計理念源于人類…

數學建模美賽論文文檔

目錄 1. 摘要&#xff1a;1.1 閱讀并理解題目1.2 背景介紹1.3 問題提出 2. 目錄&#xff1a;2.1 引言&#xff08;Introduction&#xff09;2.2 假設與合理性說明&#xff08;Assumptions and Justifications&#xff09;2.3 符號說明&#xff08;Notations&#xff09;2.4 模型…

2.Date類型的請求參數

前端 <el-form-item label"結束日期" prop"endTime"><el-date-pickerv-model"dataForm.endTime"type"date"value-format"yyyy-MM-dd HH:mm:ss"placeholder"選擇日期"></el-date-picker></el…

線下線上游戲電競陪伴APP小程序H5同城線下約玩APP開發,語聊約玩平臺搭建游戲陪玩APP源碼

開發一款線下陪玩約玩APP的實際意義和在生活中的應用場景 1、滿足社交需求:現代社會人們的社交圈往往受到時間、地點和其他限制的影響。線下陪玩約玩APP可以提供一個平臺&#xff0c;讓用戶通過約玩的方式結識新朋友、擴大社交圈 2、解決孤獨感:有些人由于工作忙碌、居住環境單…

論文閱讀2-《Dynamic Multimodal Fusion》

摘要 &#xff08;DynMM&#xff09;&#xff0c;一種新的方法&#xff0c;自適應融合多模態數據和 d在推理過程中生成依賴于數據的前向路徑。為此&#xff0c;我們提出了一種門控功能來提供基于多模態特征和一個的模態級或融合級決策提高計算效率的源感知損失函數。 細節 模…