爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      【C++】map和set的封装

      首页 知识中心 软件开发 文章详情页

      【C++】map和set的封装

      2023-07-26 08:09:37 阅读次数:422

      c++,map,set

      一、前情回顾

      set 参数只有 key,但是map除了key还有value。我们还是需要KV模型的红黑树的:

      #pragma once
      #include <iostream>
      #include <assert.h>
      #include <time.h>
      using namespace std;
      enum Color
      {
      	RED,
      	BLACK,
      };
      template<class K, class V >
      struct RBTreeNode
      {
      	pair<K, V> _kv;
      	RBTreeNode<K, V>* _left;
      	RBTreeNode<K, V>* _right;
      	RBTreeNode<K, V>* _parent;
      
      	Color _col;
      	RBTreeNode(const pair<K,V>& kv)
      		:_kv(kv)
      		,_left(nullptr)
      		,_right(nullptr)
      		,_parent(nullptr)
      		,_col(RED)
      	{}
      };
      
      template<class K,class V>
      class RBTree
      {
      	typedef RBTreeNode<K, V> Node;
      public:
      	bool Insert(const pair<K, V>& kv)
      	{
      		if (_root == nullptr)
      		{
      			_root = new Node(kv);
      			_root->_col = BLACK;
      			return true;
      		}
      		Node* parent = nullptr;
      		Node* cur = _root;
      		while (cur)
      		{
      			if (cur->_kv.first < kv.first)
      			{
      				parent = cur;
      				cur = cur->_right;
      			}
      			else if (cur->_kv.first > kv.first)
      			{
      				parent = cur;
      				cur = cur->_left;
      			}
      			else
      			{
      				return false;
      			}
      		}
      		cur = new Node(kv);
      		cur->_col = RED;
      		if (parent->_kv.first < kv.first)
      		{
      			parent->_right = cur;
      			cur->_parent = parent;
      		}
      		else
      		{
      			parent->_left = cur;
      			cur->_parent = parent;
      		}
      
      		while (parent && parent->_col == RED)
      		{
      			Node* grandfater = parent->_parent;
      			if (parent == grandfater->_left)
      			{
      				Node* uncle = grandfater->_right;
      				//情况一:u存在且为红
      				if (uncle && uncle->_col == RED)
      				{
      					parent->_col = uncle->_col = BLACK;
      					grandfater->_col = RED;
      					//向上调整
      					cur = grandfater;
      					parent = cur->_parent;
      				}
      				else
      				{
      					//情况2
      					if (cur == parent->_left)
      					{
      						RotateR(grandfater);
      						parent->_col = BLACK;
      						grandfater->_col = RED;
      					}
      					//情况3
      					else
      					{
      						//       g
      						//  p
      						//    c 
      						RotateL(parent);
      						RotateR(grandfater);
      						cur->_col = BLACK;
      						grandfater->_col = RED;
      					}
      					break;
      				}
      			}
      			else//parent==grandfater->_right
      			{
      				Node* uncle = grandfater->_left;
      				//情况1:u存在且为红色
      				if (uncle && uncle->_col == RED)
      				{
      					uncle->_col = parent->_col = BLACK;
      					grandfater->_col = RED;
      					//向上调整
      					cur = grandfater;
      					parent = cur->_parent;
      				}
      				else
      				{
      					//情况2:u不存在/u存在为黑色
      					//g
      					//    p
      					//        c
      					if (cur == parent->_right)
      					{
      						RotateL(grandfater);
      						grandfater->_col = RED;
      						parent->_col = BLACK;
      					}
      					//情况3
      					//     g
      					 //         p
      					 //      c
      					else
      					{
      						RotateR(parent);
      						RotateL(grandfater);
      						cur->_col = BLACK;
      						grandfater->_col = RED;
      					}
      					break;
      				}
      
      			}
      		}
      		//根变黑
      		_root->_col = BLACK;
      		return true;
      	}
      
      	void RotateL(Node* parent)
      	{
      		Node* subR = parent->_right;
      		Node* subRL = subR->_left;
      		parent->_right = subRL;
      		if (subRL)
      			subRL->_parent = parent;
      		Node* ppNode = parent->_parent;
      		subR->_left = parent;
      		parent->_parent = subR;
      		if (ppNode == nullptr)
      		{
      			_root = subR;
      			_root->_parent = nullptr;
      		}
      		else
      		{
      			if (ppNode->_left == parent)
      			{
      				ppNode->_left = subR;
      			}
      			else
      			{
      				ppNode->_right = subR;
      			}
      			subR->_parent = ppNode;
      		}
      	}
      
      	void RotateR(Node* parent)
      	{
      		Node* subL = parent->_left;
      		Node* subLR = subL->_right;
      		parent->_left = subLR;
      		if (subLR)
      			subLR->_parent = parent;
      		Node* ppNode = parent->_parent;
      		parent->_parent = subL;
      		subL->_right = parent;
      		if (ppNode == nullptr)
      		{
      			_root = subL;
      			_root->_parent = nullptr;
      		}
      		else
      		{
      			if (ppNode->_left == parent)
      			{
      				ppNode->_left = subL;
      			}
      			else
      			{
      				ppNode->_right = subL;
      			}
      			subL->_parent = ppNode;
      		}
      	}
      
      
      	void InOrder()
      	{
      		_InOrder(_root);
      	}
      	void _InOrder(Node* root)
      	{
      		if (root == nullptr)
      			return;
      		_InOrder(root->_left);
      		cout << root->_kv.first << ":" << root->_kv.second << endl;
      		_InOrder(root->_right);
      	}
      
      
      	bool Check(Node*root,int blackNum,int ref)
      	{
      		if (root == nullptr)
      		{
      			//cout << blackNum << endl;
      			if (blackNum != ref)
      			{
      				cout << "违反规则:本条路径的黑色结点的数量根最左路径不相等" << endl;
      				return false;
      			}
      			return true;
      		}
      		if (root->_col == RED && root->_parent->_col == RED)
      		{
      			cout << "违反规则:出现连续的红色结点" << endl;
      			return false;
      		}
      		if (root->_col == BLACK)
      		{
      			++blackNum;
      		}
      		return Check(root->_left,blackNum,ref)
      			&& Check(root->_right,blackNum,ref);
      	}
      
      	bool IsBalance()
      	{
      		if (_root == nullptr)
      		{
      			return true;
      		}
      
      		if (_root->_col != BLACK)
      		{
      			return false;
      		}
      		int ref = 0;
      		Node* left = _root;
      		while (left)
      		{
      			if (left->_col == BLACK)
      			{
      				++ref;
      			}
      			left = left->_left;
      		}
      		return Check(_root,0,ref);
      	}
      private:
      	Node* _root = nullptr;
      };
      

      二、简化源码

      翻开源码一看📕

      RBTree的结构源码:是KV结构的红黑树

      RBTree是通过传入的Value的值来判断类型,也就是一棵泛型的RBTree,通过不同的实例化,实现出了Map和Set:

      对于map:传key,对于set:传pair

      【C++】map和set的封装

      map的结构简化源码:

      【C++】map和set的封装

      set的结构简化源码:

      【C++】map和set的封装

      为了让我们的红黑树能够识别set与map我们增加一个模板参数T:

      template<class K, class T>
      class RBTree
      

      对于T模板参数可能是键值Key,也可能是由Key和Value共同构成的键值对。

      如果是set容器,那么它传入底层红黑树的模板参数就是Key和Key:

      template<class K>
      class set
      {
        private:
          RBTree<K,K> _t;
      };
      

      如果是map容器,传入底层红黑树的模板参数就是Key和Key和value的键值对:

      class map
      {
      private:
          RBTree<K, pair<const K,V>> _t;
      };
      

      通过上面,我们可以知道,对于set和map的区别:我们只要通过第二个模板参数就能进行区分,那是不是第一个模板参数就没有意义了呢?

      对于insert(const Value&v)来说,需要放入存入的值,确实是这个样子的,插入的值是value,对于set就是key,对于map就是pair。

      但是对于find(const Key&key)来说,查找的参数不是value,找的不是pair而是Key,对于map容器来说就不行了。

      **红黑树的节点**:set容器:K和T都是键值Key; map容器:K是键值Key,T由Key和Value构成的键值对;但是底层红黑树并不知道上层容器到底是map还是set,因此红黑树的结点当中直接存储T就行了,如果是set的时候,结点当中存储的是键值Key;如果是map的时候,结点当中存储的就是键值对,所以红黑树的结点定义如下,由T类型来决定红黑树存的是key还是pair:

      template<class T>
          //三叉链结构
      struct RBTreeNode
      {
      	T _data;
      	RBTreeNode<T>* _left;
      	RBTreeNode<T>* _right;
      	RBTreeNode<T>* _parent;
      
      	Color _col;
      	RBTreeNode(const T& data)
      		:_data(data)
      		, _left(nullptr)
      		, _right(nullptr)
      		, _parent(nullptr)
      		, _col(RED)
      	{}
      };
      

      三、仿函数

      这里存在一个问题📝:插入的时候data的大小如何去进行比较:我们并不知道是什么类型是key,还是pair的比较,而我们刚开始kv结构就直接用kv.first去比较了。

      对于set是Key,可以比较

      对于map是pair,那我们要取其中的first来比较,但是pair的大小并不是直接按照first去进行比较的,而我们只需要按照first去进行比较

      由于底层的红黑树不知道传的是map还是set容器,当需要进行两个结点键值的比较时,底层红黑树传入的仿函数来获取键值Key,进行两个结点键值的比较:这个时候我们就需要仿函数了,如果是set那就是用于返回T当中的键值Key,如果是map那就是用于返回pair的first:

      仿函数/函数对象也是类,是一个类对象。仿函数要重载operator()。

      namespace HWC
      {
      	template<class K,class V>
      	class map
      	{
      		struct  MapKeyOfT
      		{
      			const K& operator()(const pair<const K, V>& kv)
      			{
      				return kv.first;
      			}
      		};
      	public:
      	private:
      		RBTree<K, pair<const K,V>,MapKeyOfT> _t;
      	};
      
      namespace HWC
      {
      	template<class K>
      	class set
      	{
      		struct SetKeyOfT
      		{
      			const K& operator()(const K& key)
      			{
      				return key;
      			}
      		};
      	private:
      		RBTree<K,K,SetKeyOfT> _t;
      	};
      

      博主画了个图更加容易进行比对👇

      【C++】map和set的封装

      查找过程,此时就可以套上我们所写的仿函数对象去进行数据的大小比较了:

              KeyOfT kot;//仿函数对象
      		Node* parent = nullptr;
      		Node* cur = _root;
      		while (cur)
      		{
      			if (kot(cur->_data)<kot(data))
      			{
      				parent = cur;
      				cur = cur->_right;
      			}
      			else if (kot(cur->_data)>kot(data))
      			{
      				parent = cur;
      				cur = cur->_left;
      			}
      			else
      			{
      				return false;
      			}
      		}
      

      四、迭代器

      红黑树的正向迭代器是对结点指针进行了封装,所以这里的正向迭代器就只有一个成员变量:结点的指针,并没有什么其他的地方,迭代器的定义:

      template<class T,class Ref,class Ptr>
      struct __RBTreeIterator
      {
      	typedef RBTreeNode<T> Node;
      	typedef __RBTreeIterator<T,Ref,Ptr> Self;
      	typedef __RBTreeIterator<T, T&, T*> iterator;
      	Node* _node;
      
      	__RBTreeIterator(Node*node)
      		:_node(node)
      	{}
      
      	//普通迭代器的时候,它是拷贝构造
      	//const迭代器的时候,它是构造,支持用普通迭代器构造const迭代器
      	__RBTreeIterator(const iterator& s)
      		:_node(s._node)
      	{}
      }
      

      *:解引用操作,返回对应结点数据的引用:

      Ref operator*()
      	{
      		return _node->_data;
      	}
      

      ->:成员访问操作符,返回结点数据的引用:

      Ptr operator->()
      	{
      		return &_node->_data;
      	}
      

      !=、==:比较简单

        bool operator !=(const Self & s) const
      	{
      		return _node != s._node;
      	}
      	bool operator ==(const Self& s) const
      	{
      		return _node == s._node;
      	}
      

      这里的迭代器重点是迭代器的++:

      一个结点的正向迭代器进行++操作后,根据红黑树中序(左、根、右)找到当前结点的下一个结点,中序的第一个节点是最左,迭代器的++怎么去找:

      如果节点的右子树不为空,++就是找右子树的最左节点

      如果节点的右子树为空,++就是找祖先(孩子是父亲的左的那个祖先)

      代码实现✍:

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

      迭代器的--

      对于–,如果是根,–就是左子树,找到左子树最大的那一个(最右节点)

      如果节点的左子树不为空,--找左子树最右的节点

      如果节点的左子树为空,--找祖先(孩子是父亲的右的祖先)

      代码实现✍:

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

      不要忘记迭代器的两个核心成员:begin()与end()

      begin():返回中序(左、根、右)第一个结点的正向迭代器,即最左节点,返回的是最左节点,直接找最左节点即可

      end():返回中序(左、根、右)最后一个结点下一个位置的正向迭代器,这里直接用空指针

      template<class K, class T,class KeyOfT>
      class RBTree
      {
      	typedef RBTreeNode<T> Node;
      public:
      	typedef __RBTreeIterator<T> iterator;
      
      	iterator begin()
      	{
      		Node* left = _root;
      		while (left && left->_left)
      		{
      			left = left->_left;
      		}
      		return iterator(left);
      	}
      
      	iterator end()
      	{
      		return iterator(nullptr);
      	}
      }
      

      五、set的实现

      通过前面底层红黑树的接口进行套用即可实现set的实现:

      值得注意的是🔴:typename:没有实例化的模板,区分不了是静态变量还是类型,typename告诉编译器是类型

      #pragma once
      #include "RBTree.h"
      
      namespace hwc
      {
      	template <class K>
      	class set
      	{
      		struct SetKeyOfT
      		{
      			const K& operator()(const K& key)
      			{
      				return key;
      			}
      
      		};
      	public:
              //typename:没有实例化的模板,区分不了是静态变量还是类型,typename告诉编译器是类型
      		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;//key不可以修改
      		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
      
      		iterator begin() const 
      		{
      			return _t.begin();
      		}
      
      		iterator end() const 
      		{
      			return _t.end();
      		}
              
      		pair<iterator,bool> insert(const K& key)
      		{
                  //底层红黑树的iterator是普通迭代器
      			pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret =  _t.Insert(key);
      			return pair<iterator, bool>(ret.first, ret.second);//用普通迭代器构造const迭代器
      		}
      	private:
      		RBTree<K, K,SetKeyOfT> _t;
      	};
      
      	void test_set()
      	{
      		int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
      		set<int> s;
      		for (auto e : a)
      		{
      			s.insert(e);
      		}
      
      		set<int>::iterator it = s.begin();
      		while (it != s.end())
      		{
      			cout << *it << " ";
      			++it;
      		}
      		cout << endl;
      
      		for (auto e : s)
      		{
      			cout << e << " ";
      		}
      		cout << endl;
      	}
      }
      

      六、map的实现

      同样是套用上底层红黑树的接口,不过map的实现有一个很重要的地方,那就是[]的实现

      #pragma once
      #include "RBTree.h"
      namespace hwc
      {
      	template<class K,class V>
      	class map
      	{
      		struct MapkeyOfT
      		{
      			const K& operator()(const pair<const K, V>& kv)
      			{
      				return kv.first;
      			}
      		};
      	public:
      		//typename:没有实例化的模板,区分不了是静态变量还是类型,typename告诉编译器是类型
      		typedef typename RBTree<K, pair<const K, V>, MapkeyOfT>::iterator iterator;
      		typedef typename RBTree<K, pair<const K, V>, MapkeyOfT>::const_iterator 
      			const_iterator;
      
      		iterator begin()
      		{
      			return _t.begin();
      		}
      		iterator end()
      		{
      			return _t.end();
      		}
      
      		const_iterator begin() const
      		{
      			return _t.begin();
      		}
      		const_iterator end() const
      		{
      			return _t.end();
      		}
      		pair<iterator,bool> insert(const pair<const K, V>& kv)
      		{
      			return _t.Insert(kv);
      		}
      
      		V& operator[](const K& key)
      		{
      			pair<iterator, bool> ret = insert(make_pair(key, V()));
      			return ret.first->second;
      		}
      	private:
      		RBTree<K, pair<const K, V>, MapkeyOfT> _t;
      	};
      
      
      	void test_map()
      	{
      		int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
      		map<int, int> m;
      		for (auto e : a)
      		{
      			m.insert(make_pair(e, e));
      		}
      
      		map<int, int>::iterator it = m.begin();
      		while(it!=m.end())
      		{
      			it->second++;
      			cout << it->first << ":" << it->second << endl;
      			++it;
      		}
      		cout << endl;
      
      		map<string, int> countMap;
      		string arr[] = { "苹果","西瓜","香蕉","苹果"};
      		for (auto& e : arr)
      		{
      			countMap[e]++;
      		}
      
      		for (auto& kv : countMap)
      		{
      			cout << kv.first << ":" << kv.second << endl;
      		}
      	}
      }
      

      七、红黑树代码

      最后,在这里送上源码:

      #pragma once
      
      #pragma once
      #include <iostream>
      #include <assert.h>
      #include <time.h>
      using namespace std;
      enum Color
      {
      	RED,
      	BLACK,
      };
      template<class T>
      struct RBTreeNode
      {
      	T _data;
      	RBTreeNode<T>* _left;
      	RBTreeNode<T>* _right;
      	RBTreeNode<T>* _parent;
      
      	Color _col;
      	RBTreeNode(const T& data)
      		:_data(data)
      		, _left(nullptr)
      		, _right(nullptr)
      		, _parent(nullptr)
      		, _col(RED)
      	{}
      };
      
      template<class T,class Ref,class Ptr>
      struct __RBTreeIterator
      {
      	typedef RBTreeNode<T> Node;
      	typedef __RBTreeIterator<T,Ref,Ptr> Self;
      	typedef __RBTreeIterator<T, T&, T*> iterator;
      	Node* _node;
      
      	__RBTreeIterator(Node*node)
      		:_node(node)
      	{}
      
      
      	//普通迭代器的时候,它是拷贝构造
      	//const迭代器的时候,它是构造,支持用普通迭代器构造const迭代器
      	__RBTreeIterator(const iterator& s)
      		:_node(s._node)
      	{}
      
      	Ref operator*()
      	{
      		return _node->_data;
      	}
      	Ptr operator->()
      	{
      		return &_node->_data;
      	}
      
      	Self& operator++()
      	{
      		if (_node->_right)
      		{
      			Node* min = _node->_right;
      			while (min->_left)
      			{
      				min = min->_left;
      			}
      			_node = min;
      		}
      		else
      		{
      			Node* cur = _node;
      			Node* parent = cur->_parent;
      			while (parent && cur == parent->_right)
      			{
      				cur = cur->_parent;
      				parent = parent->_parent;
      			}
      			_node = parent;
      		}
      		return *this;
      	}
      
      	Self& operator--()
      	{
      		if (_node->_left)
      		{
      			Node* max = _node->_left;
      			while (max->_right)
      			{
      				max = max->_right;
      			}
      			_node = max;
      		}
      		else
      		{
      			Node* cur = _node;
      			Node* parent = cur->_parent;
      			while (parent&&cur==parent->_left)
      			{
      				cur = cur->_parent;
      				parent = parent->_parent;
      			}
      			_node = parent;
      		}
      		return *this;
      	}
      
      	bool operator !=(const Self & s) const
      	{
      		return _node != s._node;
      	}
      	bool operator ==(const Self& s) const
      	{
      		return _node == s._node;
      	}
      };
      
      
      template<class K, class T,class KeyOfT>
      class RBTree
      {
      	typedef RBTreeNode<T> Node;
      public:
      	typedef __RBTreeIterator<T,T&,T*> iterator;
      	typedef __RBTreeIterator<T,const T&,const T*> const_iterator;
      	const_iterator begin() const 
      	{
      		Node* left = _root;
      		while (left && left->_left)
      		{
      			left = left->_left;
      		}
      		return const_iterator(left);
      
      	}
      	const_iterator end() const 
      	{
      		return const_iterator(nullptr);
      	}
      
      	iterator begin()
      	{
      		Node* left = _root;
      		while (left && left->_left)
      		{
      			left = left->_left;
      		}
      		return iterator(left);
      
      	}
      	iterator end()
      	{
      		return iterator(nullptr);
      	}
      	pair<iterator,bool> Insert(const T& data)
      	{
      		if (_root == nullptr)
      		{
      			_root = new Node(data);
      			_root->_col = BLACK;
      			return make_pair(iterator(_root),true);
      		}
      		KeyOfT kot;
      		Node* parent = nullptr;
      		Node* cur = _root;
      		while (cur)
      		{
      			if (kot(cur->_data) < kot(data))
      			{
      				parent = cur;
      				cur = cur->_right;
      			}
      			else if (kot(cur->_data) > kot(data))
      			{
      				parent = cur;
      				cur = cur->_left;
      			}
      			else
      			{
      				return make_pair(iterator(cur),false);
      			}
      		}
      		cur = new Node(data);
      		Node* newnode = cur;
      		cur->_col = RED;
      		if (kot(parent->_data) < kot(data))
      		{
      			parent->_right = cur;
      			cur->_parent = parent;
      		}
      		else
      		{
      			parent->_left = cur;
      			cur->_parent = parent;
      		}
      
      		while (parent && parent->_col == RED)
      		{
      			Node* grandfater = parent->_parent;
      			if (parent == grandfater->_left)
      			{
      				Node* uncle = grandfater->_right;
      				//情况一:u存在且为红
      				if (uncle && uncle->_col == RED)
      				{
      					parent->_col = uncle->_col = BLACK;
      					grandfater->_col = RED;
      					//向上调整
      					cur = grandfater;
      					parent = cur->_parent;
      				}
      				else
      				{
      					//情况2
      					if (cur == parent->_left)
      					{
      						RotateR(grandfater);
      						parent->_col = BLACK;
      						grandfater->_col = RED;
      					}
      					//情况3
      					else
      					{
      						//       g
      						//  p
      						//    c 
      						RotateL(parent);
      						RotateR(grandfater);
      						cur->_col = BLACK;
      						grandfater->_col = RED;
      					}
      					break;
      				}
      			}
      			else//parent==grandfater->_right
      			{
      				Node* uncle = grandfater->_left;
      				//情况1:u存在且为红色
      				if (uncle && uncle->_col == RED)
      				{
      					uncle->_col = parent->_col = BLACK;
      					grandfater->_col = RED;
      					//向上调整
      					cur = grandfater;
      					parent = cur->_parent;
      				}
      				else
      				{
      					//情况2:u不存在/u存在为黑色
      					//g
      					//    p
      					//        c
      					if (cur == parent->_right)
      					{
      						RotateL(grandfater);
      						grandfater->_col = RED;
      						parent->_col = BLACK;
      					}
      					//情况3
      					//     g
      					 //         p
      					 //      c
      					else
      					{
      						RotateR(parent);
      						RotateL(grandfater);
      						cur->_col = BLACK;
      						grandfater->_col = RED;
      					}
      					break;
      				}
      
      			}
      		}
      		//根变黑
      		_root->_col = BLACK;
      		return make_pair(iterator(newnode),true);
      	}
      
      	void RotateL(Node* parent)
      	{
      		Node* subR = parent->_right;
      		Node* subRL = subR->_left;
      		parent->_right = subRL;
      		if (subRL)
      			subRL->_parent = parent;
      		Node* ppNode = parent->_parent;
      		subR->_left = parent;
      		parent->_parent = subR;
      		if (ppNode == nullptr)
      		{
      			_root = subR;
      			_root->_parent = nullptr;
      		}
      		else
      		{
      			if (ppNode->_left == parent)
      			{
      				ppNode->_left = subR;
      			}
      			else
      			{
      				ppNode->_right = subR;
      			}
      			subR->_parent = ppNode;
      		}
      	}
      
      	void RotateR(Node* parent)
      	{
      		Node* subL = parent->_left;
      		Node* subLR = subL->_right;
      		parent->_left = subLR;
      		if (subLR)
      			subLR->_parent = parent;
      		Node* ppNode = parent->_parent;
      		parent->_parent = subL;
      		subL->_right = parent;
      		if (ppNode == nullptr)
      		{
      			_root = subL;
      			_root->_parent = nullptr;
      		}
      		else
      		{
      			if (ppNode->_left == parent)
      			{
      				ppNode->_left = subL;
      			}
      			else
      			{
      				ppNode->_right = subL;
      			}
      			subL->_parent = ppNode;
      		}
      	}
      
      
      	void InOrder()
      	{
      		_InOrder(_root);
      	}
      	void _InOrder(Node* root)
      	{
      		if (root == nullptr)
      			return;
      		_InOrder(root->_left);
      		cout << root->_kv.first << ":" << root->_kv.second << endl;
      		_InOrder(root->_right);
      	}
      
      
      	bool Check(Node* root, int blackNum, int ref)
      	{
      		if (root == nullptr)
      		{
      			//cout << blackNum << endl;
      			if (blackNum != ref)
      			{
      				cout << "违反规则:本条路径的黑色结点的数量根最左路径不相等" << endl;
      				return false;
      			}
      			return true;
      		}
      		if (root->_col == RED && root->_parent->_col == RED)
      		{
      			cout << "违反规则:出现连续的红色结点" << endl;
      			return false;
      		}
      		if (root->_col == BLACK)
      		{
      			++blackNum;
      		}
      		return Check(root->_left, blackNum, ref)
      			&& Check(root->_right, blackNum, ref);
      	}
      
      	bool IsBalance()
      	{
      		if (_root == nullptr)
      		{
      			return true;
      		}
      
      		if (_root->_col != BLACK)
      		{
      			return false;
      		}
      		int ref = 0;
      		Node* left = _root;
      		while (left)
      		{
      			if (left->_col == BLACK)
      			{
      				++ref;
      			}
      			left = left->_left;
      		}
      		return Check(_root, 0, ref);
      	}
      private:
      	Node* _root = nullptr;
      };
      

      本篇结束…

      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://blog.csdn.net/weixin_60478154/article/details/129126892,作者:平凡的人1,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:【C语言】带你玩转数组(全程高能)

      下一篇:【C++】RBTree——红黑树

      相关文章

      2025-05-19 09:04:53

      查看RISC-V版本的gcc中默认定义的宏

      查看RISC-V版本的gcc中默认定义的宏

      2025-05-19 09:04:53
      c++ , linux
      2025-05-16 09:15:24

      Redis Set集合

      Redis Set集合

      2025-05-16 09:15:24
      set , 个数 , 元素 , 示例 , 集合
      2025-05-14 10:03:13

      【Mybatis】-动态SQL

      【Mybatis】-动态SQL

      2025-05-14 10:03:13
      include , set , sql , SQL , 条件 , 标签
      2025-05-13 09:50:17

      java实现-13. 罗马数字转整数

      罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

      2025-05-13 09:50:17
      map , 字符 , 字符串 , 数字 , 罗马数字 , 表示
      2025-04-22 09:28:19

      策略模式的两种实现方式--枚举和map

      策略模式的两种实现方式--枚举和map

      2025-04-22 09:28:19
      map , 不同 , 接口 , 方法 , 枚举
      2025-04-22 09:27:17

      蓝桥杯算法竞赛系列第九章·巧解哈希题,用这3种数据类型足矣

      蓝桥杯算法竞赛系列第九章·巧解哈希题,用这3种数据类型足矣

      2025-04-22 09:27:17
      key , map , nums , 哈希 , 数组
      2025-04-18 07:11:19

      把target做一致性哈希进行分发

      把target做一致性哈希进行分发

      2025-04-18 07:11:19
      map , target , 哈希 , 节点
      2025-04-15 09:19:45

      文心一言 VS 讯飞星火 VS chatgpt (262)-- 算法导论20.1 1题

      在Go语言中,如果你想要一个数据结构支持重复的关键字(或键),你不能简单地使用内建的map,因为map在Go中是基于键的唯一性设计的。

      2025-04-15 09:19:45
      map , 关键字 , 数据结构 , 示例 , 重复
      2025-04-14 09:28:41

      【C++】set模拟实现

      C++中的set是标准模板库(STL)中的一种关联容器,它存储了一组唯一的元素,并且这些元素是按照特定的顺序(默认是升序)进行排序的

      2025-04-14 09:28:41
      set , 元素 , 插入 , 红黑树 , 迭代
      2025-04-14 09:26:51

      【算法入门08】青蛙跳台阶

      【算法入门08】青蛙跳台阶

      2025-04-14 09:26:51
      c++ , 动态规划 , 算法
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5243383

      查看更多

      最新文章

      Redis Set集合

      2025-05-16 09:15:24

      策略模式的两种实现方式--枚举和map

      2025-04-22 09:28:19

      【C++】set模拟实现

      2025-04-14 09:28:41

      [快学Python3]Sets(集合)

      2025-04-09 09:16:42

      golang与 C++数据结构类型对应关系是怎样的?

      2025-04-01 10:29:12

      MFC编程 -- 判断是否按下ctrl和shift键

      2025-03-31 08:49:25

      查看更多

      热门文章

      Lambda函数

      2023-02-08 10:33:56

      QT中多线程的使用

      2023-02-07 10:34:04

      0030 简单的四则运算 c/c++

      2023-03-21 10:39:47

      C++虚函数知识点总结

      2023-02-21 06:21:46

      (10)Qt对象模型

      2023-02-13 07:55:59

      【C&C++】二进制数据的位运算(如何存储字符)

      2023-04-10 08:53:37

      查看更多

      热门标签

      java Java python 编程开发 代码 开发语言 算法 线程 Python html 数组 C++ 元素 javascript c++
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      P3383 【模板】线性筛素数(C++_数论_欧拉筛)

      LeetCode刷题(17)【中等】两数相加(C++)

      乘法逆元代码模板

      并查集代码模板

      【Autowired自动注入map】

      C语言解题 || 统计闰年

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号