c++ map set底层模拟实现

关于这两个数据结构的insert接口实现 请看这篇文章  https://blog.csdn.net/l23456789mmmmm/article/details/139500413?spm=1001.2014.3001.5501

map::operator[]底层实现请看这篇文章 c++map类operator[]详解_c++ map operator-CSDN博客

红黑树模拟实现

#pragma once
#include <vector>
#include <iostream>
#include <queue>namespace mystl {enum COLOR {RED,BLACK};template<class K,class V>struct ListNode {				// 节点//typedef ListNode<K, V> node;using Node = ListNode<K, V>;ListNode(std::pair<K,V> kv):_kv(kv) {_parent = _left = _right = nullptr;_color = RED;}Node* _parent;Node* _left;Node* _right;std::pair<K, V> _kv;COLOR _color;};template<class K,class V,class Ref = V& ,class Ptr = V*>struct RBTree_Iterator {			//迭代器using Node = ListNode<K, V>;using iterator = RBTree_Iterator<K, V>;RBTree_Iterator(Node* node) {_node = node;}Ref operator*() {return _node->_kv.second;}Ptr operator->() {//return &(this->operator*());return &(_node->_kv.second);}bool operator!=(iterator it) {return _node != it._node;}iterator operator++() {if (_node->_right) {Node* leftMin = _node->_right;while (leftMin->_left) {leftMin = leftMin->_left;}_node = leftMin;}else{Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = parent->_parent;}_node = parent;}return *this;}Node* _node;};template<class K,class V,class Compare = std::less<K>> // class Alloc = std::allocator<pair<const K, V> > > 这个是空间适配器,先不理他class RBTree {						// 红黑树using Node = ListNode<K, V>;public:using iterator = RBTree_Iterator<K, V, V&, V*>;using const_iterator = RBTree_Iterator<K, V, const V&, const V*>;Node* GetRoot() {return _root;}size_t Size() {return _size;}void print() {std::queue<Node*> s1 ,s2;s1.push(_root);while (!s1.empty()) {while (!s1.empty()) {if (s1.front()) {s2.push(s1.front()->_left);//std::cout << s1.front()->_kv.first <<' ';printf("   %d : %d   ", s1.front()->_kv.first, s1.front()->_color);s2.push(s1.front()->_right);}else {printf("   #   ");}s1.pop();}std::swap(s1, s2);std::cout << std::endl;}}std::pair<iterator,bool> insert(const std::pair<K, V>& kv) {Node* new_node = new Node(kv);_size++;if (_root == nullptr) {new_node->_color = BLACK;_root = new_node;return std::make_pair(iterator(new_node), true);}Node* child = _root;Node* father = _root;	// 父子交替,找 新节点应该插入的地方while (child) {			//儿子不是空father = child;if (child->_kv.first > kv.first) {child = child->_left;}else if (kv.first > child->_kv.first) {child = child->_right;}else {_size--;return std::make_pair(iterator(child), false);}}//此处儿子是空,代表新节点应该插入的地方add_node(father, new_node);//对插入的节点进行检查,不合理的地方重构reconstitution(new_node);return std::make_pair(iterator(new_node), true);}bool IsValidRBTree(){Node* pRoot = GetRoot();// 空树也是红黑树if (nullptr == pRoot)return true;// 检测根节点是否满足情况if (BLACK != pRoot->_color){std::cout << "违反红黑树性质二:根节点必须为黑色" << std::endl;return false;}// 获取任意一条路径中黑色节点的个数size_t blackCount = 0;Node* pCur = pRoot;while (pCur){if (BLACK == pCur->_color)blackCount++;pCur = pCur->_left;}// 检测是否满足红黑树的性质,k用来记录路径中黑色节点的个数size_t k = 0;return _IsValidRBTree(pRoot, k, blackCount);}V& operator[](const K key) {return insert({ key,V() }).first->second;}iterator begin() {Node* tmp = _root;while (tmp && tmp->_left) {tmp = tmp->_left;}return tmp;}iterator end() {return nullptr;}const_iterator cbegin() {Node* tmp = _root;while (tmp && tmp->_left) {tmp = tmp->_left;}return tmp;}const_iterator cend() {return nullptr;}protected:void add_node(Node* father, Node* new_node) {if (new_node->_kv.first > father->_kv.first) {father->_right = new_node;}else {father->_left = new_node;}new_node->_parent = father;}void reconstitution(Node* new_node) {/*1. 每个结点不是红色就是黑色 2. 根节点是黑色的  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)*/if (new_node == _root) {return;}if (new_node->_parent->_color == BLACK)	// 父亲是黑色,插入红色节点,符合红黑树要求,不做处理return;// 父亲是红色,此时不符合条件三,需要发生重构Node* parent = new_node->_parent;				// 新节点的父节点Node* grandparent = new_node->_parent->_parent; // 爷爷节点Node* uncle = nullptr;							// 叔叔节点if (grandparent->_left == parent) {				// 叔叔节点需要通过父亲节点与爷爷节点的关系来判断uncle = grandparent->_right;			}else {uncle = grandparent->_left;}// 判断情况if (uncle == nullptr || uncle->_color == BLACK) {							// 叔叔为空,需要发生旋转Node* tmp = revorve(new_node, parent, grandparent);if (tmp == _root) {tmp->_color = BLACK;}else {reconstitution(tmp);}}else if (uncle->_color == RED) {// 叔叔为红色 需要改变颜色,并继续向上重构,因为新的爷爷节点被强制改为红色,需要继续向上重构uncle->_color = parent->_color = BLACK;if (grandparent != _root) {// 爷爷节点不为root的话grandparent->_color = RED;reconstitution(grandparent);}}//else {	// 叔叔节点为黑色//	// 旋转//	reconstitution(revorve(new_node, parent, grandparent));//}}Node* revorve(Node* node,Node* parent,Node* grandparnt) {if (node == parent->_left && parent == grandparnt->_left) {// 子为父左,父为爷左,右旋父revorveR(parent);node->_color = BLACK;return parent;}else if(node == parent->_left && parent == grandparnt->_right) {// 子为父左,父为爷右,右旋子,左旋子revorveR(node);revorveL(node);parent->_color = BLACK;return node;}else if (node == parent->_right && parent == grandparnt->_right) {// 子为父右,父为爷右,左旋父revorveL(parent);node->_color = BLACK;return parent;}else {// 子为父右,父为爷左,左旋子,右旋子revorveL(node);revorveR(node);parent->_color = BLACK;return node;}}void revorveL(Node* node){// 左旋需要改变node节点的 1.本身 2.父节点 3.爷爷节点 4.左孩子节点 共计四个节点// 记录四个节点的值,防止等下修改时混乱Node* parent = node->_parent;Node* grandparent = parent->_parent;Node* leftchild = node->_left;// 1.修改本身节点node->_parent = grandparent;node->_left = parent;// 2.修改父节点parent->_parent = node;parent->_right = leftchild;if (parent == _root)_root = node;// 3. 修改爷爷节点if (grandparent != nullptr) {if (grandparent->_left == parent)grandparent->_left = node;else {grandparent->_right = node;}}// 4. 修改左孩子节点if(leftchild != nullptr)leftchild->_parent = parent;}void revorveR(Node* node){// 右旋需要改变node节点的 1.本身 2.父节点 3.爷爷节点 4.右孩子节点 共计四个节点// 记录四个节点的值,防止等下修改时混乱Node* parent = node->_parent;Node* grandparent = parent->_parent;Node* rightchild = node->_right;// 1.修改本身节点node->_parent = grandparent;node->_right = parent;// 2.修改父节点parent->_parent = node;parent->_left = rightchild;// 3. 修改爷爷节点if (grandparent != nullptr) {if (grandparent->_left == parent)grandparent->_left = node;else {grandparent->_right = node;}}// 4. 修改右孩子节点if(rightchild!=nullptr)rightchild->_parent = parent;}bool _IsValidRBTree(Node* pRoot, size_t k, const size_t blackCount) {//走到null之后,判断k和black是否相等if (nullptr == pRoot){if (k != blackCount){std::cout << "违反性质四:每条路径中黑色节点的个数必须相同" << std::endl;return false;}return true;}// 统计黑色节点的个数if (BLACK == pRoot->_color)k++;// 检测当前节点与其双亲是否都为红色Node* pParent = pRoot->_parent;if (pParent && RED == pParent->_color && RED == pRoot->_color){std::cout << "违反性质三:没有连在一起的红色节点" << std::endl;return false;}return _IsValidRBTree(pRoot->_left, k, blackCount) &&_IsValidRBTree(pRoot->_right, k, blackCount);}private:Node* _root = nullptr;size_t _size = 0;};
}

set封装

#pragma once
#include "RBTree.h"
namespace mystl {template<class K>class set {public:using RBT = RBTree< const K, K>;using iterator = RBTree_Iterator<const K, K, K&, K*>;using const_iterator = RBTree_Iterator<const K, K, const K&, const K*>;iterator begin() {return _Tree.begin();}iterator end() {return _Tree.end();}const_iterator cbegin() const {return _Tree.cbegin;}const_iterator cend() const {return _Tree.cend();}bool operator != (set<K>& newset) {return _Tree != newset._Tree;}std::pair<iterator, bool>& insert(const K k) {return _Tree.insert(std::make_pair(k,k));}iterator find(const K& key) {return insert({ key,key }).first;}size_t size() {return _Tree.Size();}bool IsRBTree() {return _Tree.IsValidRBTree();}private:RBT _Tree;};
}

map封装

#pragma once
#include "RBTree.h"
namespace mystl {template<class K,class V>class map { public:using RBT = RBTree< const K, std::pair<const K, V>>;using iterator = RBTree_Iterator<const K, std::pair<const K, V>, std::pair<const K,V>&,std::pair<const K, V> *>;using const_iterator = RBTree_Iterator<const K, std::pair<const K, V>, const std::pair<const K, V>&,const std::pair<const K, V>*>;iterator begin() {return _Tree.begin();}iterator end() {return _Tree.end();}const_iterator cbegin() const {return _Tree.cbegin;}const_iterator cend() const {return _Tree.cend();}std::pair<iterator, bool> insert(const std::pair<K, V> &kv) {return _Tree.insert({ kv.first,kv });}iterator find(const K& key) {return insert({key,V()}).first;}bool operator != (const map<K,V>& newmap) {return _Tree != newmap._Tree;}V& operator[](const K& key) {//_Tree.insert(std::pair<key,std::pair<key,V()> >);iterator ret = _Tree.insert({key,{key,V()}}).first;//iterator ret = _Tree.insert({ key,{key,V()} }).first;//std::pair<iterator, bool> ret = _Tree.insert(std::make_pair(key, V()));return ret._node->_kv.second.second;}size_t size() {return _Tree.Size();}bool IsRBTree() {return _Tree.IsValidRBTree();}private:RBT _Tree;};
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/30151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java面试八股之myBatis与myBatis plus的对比

myBatis与myBatis plus的对比 基础与增强&#xff1a; MyBatis 是一个成熟的Java持久层框架&#xff0c;它允许开发者通过XML文件或注解来配置SQL语句和数据库映射&#xff0c;提供了一个灵活的方式来操作数据库&#xff0c;但需要手动编写所有的SQL语句和结果集映射。 MyBa…

Day55 代码随想录打卡|二叉树篇---二叉搜索树中的插入操作

题目&#xff08;leecode T701&#xff09;&#xff1a; 给定二叉搜索树&#xff08;BST&#xff09;的根节点 root 和要插入树中的值 value &#xff0c;将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 &#xff0c;新值和原始二叉搜索树中的任意节点值…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【11】ElasticSearch

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【11】ElasticSearch 简介基本概念ElasticSearch概念-倒排索引安装基本命令ik 分词器SpringBoot整合测试存储数据&#xff1a;测试复杂检索同步与异步调用 参考 简介 Elasticsearch 是一…

【AIGC】MetaGPT原理以及应用

目录 MetaGPT原理 MetaGPT应用 MetaGPT和传统编程语言相比有什么优势和劣势 视频中的PPT 参考资料 MetaGPT原理 MetaGPT是一种多智能体框架&#xff0c;它结合了元编程技术&#xff0c;通过标准化操作程序&#xff08;SOPs&#xff09;来协调基于大语言模型的多智能体系统…

Zookeeper 集群节点选举原理实现(三)

Zookeeper 集群节点选举原理实现(三) 刚部署三个节点或者多个节点启动时,此时还未选择出领导节点,不同节点的初始化zxid 是如何保证不重复不冲突有序呢? 在 Zookeeper 集群的初始启动阶段,所有节点会在选举领导节点之前先初始化自己的状态和 ZXID。为了确保不同节点的初始…

jieba中文分词器的使用

Jieba 是一个中文分词的第三方库&#xff0c;主要用于对中文文本进行分词。分词是将文本分割成一个个词语的过程&#xff0c;这在中文文本处理中尤为重要&#xff0c;因为中文不像英文那样有明显的空格来分隔词语。Jieba 的分词算法可以实现精确分词、全模式分词和搜索引擎模式…

嵌入式实验---实验一 通用GPIO实验

一、实验目的 1、掌握STM32F103 GPIO程序设计流程&#xff1b; 2、熟悉STM32固件库的基本使用。 二、实验原理 1、通过按键实现&#xff1a;按键按下&#xff0c;LED点亮&#xff1b;按键释放&#xff0c;LED熄灭。 三、实验设备和器材 电脑、Keil uVision5软件、Proteus…

Hierarchical Integration Diffusion Model for Realistic Image Deblurring

neurips23 上交&ETH&字节&清华&上海ai lab&悉尼大学&西湖大学https://github.com/zhengchen1999/HI-Diff 问题引入 现在的diffusion的方法在sample的时候需要的iteration过多&#xff0c;所以本文提出在高度压缩的空间进行DM&#xff0c;且deblur模型…

力扣第209题“长度最小的子数组”

关注微信公众号 数据分析螺丝钉 免费领取价值万元的python/java/商业分析/数据结构与算法学习资料 在本篇文章中&#xff0c;我们将详细解读力扣第209题“长度最小的子数组”。通过学习本篇文章&#xff0c;读者将掌握如何使用滑动窗口和双指针的方法来解决这一问题&#xff0…

甲辰年五月十四风雨思

甲辰年五月十四风雨思 夜雨消暑气&#xff0c;远光归家心。 ​只待万窗明&#xff0c;朝夕千家勤。 ​苦乐言行得&#xff0c;酸甜日常品。 宫商角徵羽&#xff0c;​仁义礼智信。

【python】PyCharm如何设置字体大小和背景

目录 效果展示 字体大小 背景设置 效果展示 字体大小 再左上角找到四条杠的图标 找到File 一般字体大小为22最合适&#xff0c;行间距为默认 背景设置 还是再字体设置的页面搜索 background 小编的其他文章详见&#xff0c;欢迎来支持 东洛的克莱斯韦克-CSDN博客 【机器…

如何优雅的一键下载OpenHarmony活跃分支代码?请关注【itopen: ohos_download】

itopen组织&#xff1a;1、提供OpenHarmony优雅实用的小工具2、手把手适配riscv qemu linux的三方库移植3、未来计划riscv qemu ohos的三方库移植 小程序开发4、一切拥抱开源&#xff0c;拥抱国产化 一、概述 为方便大家每次下载OpenHarmony不同分支/tag代码&#xff0c…

【文末附gpt升级秘笈】“登月游戏”对人类的意义

“登月游戏”对人类的意义是多方面的&#xff0c;不仅体现在科技、教育和娱乐层面&#xff0c;还对人类探索未知的精神产生了深远影响。 一、科技意义 “登月游戏”作为早期计算机游戏的代表之一&#xff0c;展示了计算机技术在模拟现实世界方面的能力。通过模拟登月器的着陆…

数据库-单表查询-排序和分组

对查询结果排序&#xff1a; SELECT 字段名 FROM 表名 ORDER BY 字段名 [ASC[DESC]]; ASC 升序关键字DESC 降序关键字 分组查询的单独使用: SELECT 字段名 FROM 表名 GROUP BY 字段名; 使用 LIMIT 限制查询结果的数量: SELECT 字段名 FROM 表名 LIMIT [OFFSET,] 记录数; 第一个…

程序员失业了,你可以做这些事情

这篇文章&#xff0c;我们讲&#xff0c;你先别带入自己哈&#xff0c;如果失业了&#xff0c;放心吧&#xff0c;你那么有上进心&#xff0c;不会失业的。咱就是说&#xff0c;如果万一失业了&#xff0c;你可以做这些事情。 1 体力好的铁人三项 &#x1f469;‍&#x1f3e…

Kotlin 编程语言详解:特点、应用领域及语法教程

什么是 Kotlin&#xff1f; Kotlin 是一种现代、流行的编程语言&#xff0c;由 JetBrains 在 2016 年发布。 自发布以来&#xff0c;它已经变得非常流行&#xff0c;因为它与 Java 兼容&#xff08;Java 是目前最流行的编程语言之一&#xff09;&#xff0c;这意味着 Java 代…

Python基础-引用参数、斐波那契数列、无极分类

1.引用参数的问题 &#xff08;1&#xff09;列表&#xff08;list&#xff09; 引用参数&#xff0c;传地址的参数&#xff0c;即list1会因list2修改而改变。 list1 [1,2,3,4] list2 list1 print(list1) list2[2] 1 print(list2) print(list1)非引用参数&#xff0c;不传…

【Java】线程池技术(一)Executor框架

背景 Java 底层提供了 Thread 类支持开发人员手动创建线程执行任务&#xff0c;但是这种操作会存在以下问题&#xff1a; 每次都要重新创造和回收 Thread 对象&#xff0c;性能较差。如果并发线程数较大&#xff0c;且任务执行时间较短&#xff0c;频繁创建和回收线程对象会大…

解锁TikTok内容趋势——高效获取TikTok标签信息接口

一、引言 在TikTok这个全球热门的短视频平台上&#xff0c;标签&#xff08;Hashtags&#xff09;是用户和内容创作者连接、发现新内容的重要工具。为了帮助品牌、市场分析师、内容创作者等更好地理解和利用TikTok上的内容趋势&#xff0c;我们推出了一款全新的接口服务&#…