C++ ──── set和map的模拟实现

目录

[1. 因为set和map底层都是红黑树,因此直接改造红黑树即可](#1. 因为set和map底层都是红黑树,因此直接改造红黑树即可)

[2. 红黑树的三个模版参数](#2. 红黑树的三个模版参数)

[3.红黑树实现迭代器(++ -- *() ->() != ==)](#3.红黑树实现迭代器(++ -- *() ->() != ==))

4.封装set

5.封装map

红黑树


红黑树的迭代器

迭代器的好处是可以方便遍历,是数据结构的底层实现与用户透明。如果想要给红黑树增加迭代器,需要考虑以前问题: begin()与end() STL明确规定,begin()与end()代表的是一段前闭后开的区间,而对红黑树进行中序遍历后, 可以得到一个有序的序列,

因此:begin()可以放在红黑树中**最小节点(即最左侧节点)**的位置,end()放在最大节点(最右侧节点)的下一个位置,关键是最大节点的下一个位置在哪块?

能否给成nullptr呢?

答案是也可以,但是对end()位置的迭代器进行 - - 操作,必须要能找最后一个元素,最好的方式是将end()放在头结点的位置:

**1.**因为set和map底层都是红黑树,因此直接改造红黑树即可

set 存Key ,而map存的是pair<key ,value > ,因此将红黑树的节点存储改为T,传什么就存储什么

2. 红黑树的三个模版参数

因为红黑树中的Find 和Erase 需要传key来查找 和删除

Insert 和 Node 需要插入T

所以要传两个模版参数K 和 T

但是在函数insert中map存储的pair 和set存储的key 红黑树并不知道是哪个进而无法比较大小来确定位置,所以还要传一个仿函数来取key ,第三个模版参数keyOfT

3.红黑树实现迭代器(++ -- *() ->() != ==)

在红黑树里实现begin() 和end()

4.封装set

cpp 复制代码
#pragma once
#include"RBTree.h"

namespace BMH
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;//set迭代器不支持修改,因为红黑底层是搜索树
		typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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 K& key)
		{
			return _t.Insert(key);
		}

		iterator find(const K& key)
		{
			return _t.Find(key);
		}

	private:
		RBTree<K, const K, SetKeyOfT> _t;
	};
	void Print(const set<int>& s)
	{
		set<int>::const_iterator it = s.end();
		while (it != s.begin())
		{
			--it;
			//*it += 2;  set不能修改
			cout << *it << " ";
		}
		cout << endl;
	}

	void test_set()
	{
		set<int> s;
		int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
		for (auto e : a)
		{
			s.insert(e);
		}

		for (auto e : s)
		{
			cout << e << " ";
		}
		cout << endl;

		set<int>::iterator it = s.end();
		while (it != s.begin())
		{
			--it;

			cout << *it << " ";
		}
		cout << endl;

		it = s.begin();
		//*it += 10;
		while (it != s.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;

		Print(s);
	}
}

map的底层结构就是红黑树,因此在map中直接封装一棵红黑树,然后将其接口包装下即可

5.封装map

cpp 复制代码
#pragma once
#include"RBTree.h"

namespace BMH
{
	template<class K ,class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K,V>& KV)
			{
				return KV.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::Iterator iterator;//因为map的key不能改,V可以改 所以key加上const
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::ConstIterator const_iterator;//因为map的key不能改,V可以改 所以key加上const
		iterator begin()
		{
			return _t.Begin();
		}

		iterator end()
		{
			return _t.End();
		}
		const_iterator begin() const
		{
			return _t.Begin();
		}

		const_iterator end() const
		{
			return _t.End();
		}

		iterator find(const K& key)
		{
			return _t.Find(key);
		}
		pair<iterator, bool> insert(const pair<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;//因为map的key不能改,V可以改 所以key加上const
	};

	void test_map()
	{
		map<string, string> dict;
		dict.insert({ "sort", "排序" });
		dict.insert({ "left", "左边" });
		dict.insert({ "right", "右边" });

		dict["left"] = "左边,剩余";
		dict["insert"] = "插入";
		dict["string"];

		map<string, string>::iterator it = dict.begin();
		while (it != dict.end())
		{
			// 不能修改first,可以修改second
			//it->first += 'x';
			it->second += 'x';

			cout << it->first << ":" << it->second << endl;
			++it;
		}
		cout << endl;
	}
}

红黑树

cpp 复制代码
#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

enum Colour
{
	RED,
	BLACK
};

template <class T>
struct RBTNode
{

	T _data;
	RBTNode* _left;
	RBTNode* _right;
	RBTNode* _parent;
	Colour _col;

	RBTNode(const T& data)
		:_data(data)
		, _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
	{}
};
template<class T, class Ref ,class Ptr>//增加Ref 和Ptr 为了使其也能实现const_iterator
struct RBTIterator
{
	typedef RBTNode<T> Node;
	typedef RBTIterator<T, Ref,Ptr> Self;

	Node* _node;
	Node* _root;
	RBTIterator(Node* node, Node* root)
		:_node(node)
		,_root(root)
	{}

	Self&  operator++()
	{
		if (_node->_right)//右不为空,下一个为右子树的最左节点
		{
			Node* LeftMost = _node->_right;
			while (LeftMost->_left)
			{
				LeftMost = LeftMost->_left;
			}
			_node = LeftMost;
		}
		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 == nullptr) // end()
		{
			// --end(),特殊处理,走到中序最后一个节点,整棵树的最右节点
			Node* rightMost = _root;
			while (rightMost && rightMost->_right)
			{
				rightMost = rightMost->_right;
			}

			_node = rightMost;
		}
		else if (_node->_left)//存在左边,找左子树最右边
		{
			Node* Mostright = _node->_left;
			while(Mostright->_right)
			{
				Mostright = Mostright->_right;
			}
			_node = Mostright;
		}
		else//不存在左边,找有右孩子的祖先
		{
			Node* cur = _node;
			Node* parent = _node->_parent;
			while (parent && parent->_left == cur)
			{
				cur = parent;
				parent = cur->_parent;
			}
			_node = parent;
		}
		return *this;
	}

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

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

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

template<class K, class T, class KeyOfT>
class RBTree
{
	typedef RBTNode<T>  Node;
	
public:
	typedef RBTIterator<T, T&, T*> Iterator;
	typedef RBTIterator<T, const T&, const T*>  ConstIterator;

	Iterator Begin()
	{
		Node* LeftMost = _root;
		while (LeftMost && LeftMost->_left)
		{
			LeftMost = LeftMost->_left;
		}
		return Iterator(LeftMost, _root);
	}

	Iterator End()
	{
		return Iterator(nullptr ,_root);
	}

	ConstIterator Begin()const
	{
		Node* LeftMost = _root;
		while (LeftMost && LeftMost->_left)
		{
			LeftMost = LeftMost->_left;
		}
		return ConstIterator(LeftMost, _root);
	}

	ConstIterator End() const
	{
		return ConstIterator(nullptr, _root);
	} 

	RBTree()
		:_root(nullptr)
	{}

	RBTree(const RBTree<K, T, KeyOfT>& t)
	{
		_root = Copy(t._root);
	}

	~RBTree()
	{
		Destroy(_root);
		_root = nullptr;
	}
	void Inorder()
	{
		_Inorder(_root);
	}

	Iterator Find(const K& key)
	{
		//从根开始找
		Node* cur = _root;
		KeyOfT KOT;
		while (cur)
		{
			
			if (KOT(cur) > key)
			{
				cur = cur->_left;
			}
			else if (KOT(cur) < key)
			{
				cur = cur->_right;
			}
			else
			{
				return Iterator(cur,_root);
			}

		}
		return End();
	}

	pair<Iterator, bool> Insert(const T& data)
	{
		//第一个结点
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return std::make_pair(Iterator(_root ,_root), true);
		}
		//从根开始找,看看有没有,没有再插入
		Node* cur = _root;
		Node* parent = nullptr;//parent是要插入位置的父亲
		KeyOfT KOT;
		while (cur)
		{

			if (KOT(cur->_data) > KOT(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (KOT(cur->_data) < KOT(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				//找到了,不用插入
				return std::make_pair(Iterator(cur, _root), false);
			}
		}

		Node* newNode = new Node(data);
		//新增节点,颜色给红色
		newNode->_col = RED;
		if (KOT(parent->_data) < KOT(data))
		{
			parent->_right = newNode;
		}
		else
		{
			parent->_left = newNode;
		}
		newNode->_parent = parent;

		cur = newNode;
		//父亲为黑色直接结束
		//父亲节点为红色(出现双红情况),进行处理
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			//      g
			//	 p
			//new
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;

				if (uncle && uncle->_col == RED)// u存在且为红 -》变色再继续往上处理
				{
					//      g
					//	 p    u
					//new
					parent->_col = BLACK;
					uncle->_col = BLACK;
					grandfather->_col = RED;

					//向上处理
					cur = grandfather;
					parent = cur->_parent;

				}
				else// u不存在或存在且为黑
				{
					//      g		       g
					//	 p			    p     u
					//cur			cur
					if (cur == parent->_left)//右单旋
					{
						RotateR(grandfather);

						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else//双旋
					{
						//      g				 g
						//	 p				  p		 u
						//		cur				cur
						RotateL(parent);
						RotateR(grandfather);

						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else
			{
				//    g
				//	u	p
				//		  new
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{

					//      g
					//	 u     p
					//			new
					parent->_col = BLACK;
					uncle->_col = BLACK;
					grandfather->_col = RED;

					//向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					//      g		        g
					//	 	   p        u      p  
					//			cur			    cur
					if (cur == parent->_right)//单旋
					{
						RotateL(grandfather);

						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//       g		         g
						//	 	    p        u       p  
						//		cur			    cur
						RotateR(parent);
						RotateL(grandfather);

						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;

				}

			}
		}

		_root->_col = BLACK;
		return std::make_pair(Iterator(newNode, _root), true);
	}

	bool IsBalance()
	{
		if (_root == nullptr)
			return true;

		if (_root->_col == RED)
		{
			return false;
		}

		// 参考值
		int refNum = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				++refNum;
			}

			cur = cur->_left;
		}

		return Check(_root, 0, refNum);
	}


private:
	bool Check(Node* root, int blackNum, const int refNum)
	{
		KeyOfT KOT;
		if (root == nullptr)
		{
			//cout << blackNum << endl;
			if (refNum != blackNum)
			{
				cout << "存在黑色节点的数量不相等的路径" << endl;
				return false;
			}

			return true;
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << KOT(root->_data) << "存在连续的红色节点" << endl;
			return false;
		}

		if (root->_col == BLACK)
		{
			blackNum++;
		}

		return Check(root->_left, blackNum, refNum)
			&& Check(root->_right, blackNum, refNum);
	}

	int _Height(Node* Root)
	{
		if (Root == nullptr)
			return 0;
		int leftHeight = _Height(Root->_left);
		int rightHeight = _Height(Root->_right);

		return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	}

	void RotateR(Node* parent)
	{
		if (parent == nullptr)
			return;

		Node* SubL = parent->_left;
		Node* SubLR = SubL->_right;
		Node* parent2 = parent->_parent;

		parent->_left = SubLR;
		if (SubLR)
		{
			SubLR->_parent = parent;
		}

		SubL->_right = parent;
		parent->_parent = SubL;

		if (parent2)
		{
			if (parent2->_left == parent)
			{
				parent2->_left = SubL;
			}
			else
			{
				parent2->_right = SubL;
			}
			SubL->_parent = parent2;
		}
		else
		{
			_root = SubL;
			SubL->_parent = nullptr;//容易忘
		}
	}
	void RotateL(Node* parent)
	{
		if (parent == nullptr)
			return;

		Node* SubR = parent->_right;
		Node* SubRL = SubR->_left;
		Node* parent2 = parent->_parent;

		parent->_parent = SubR;
		SubR->_left = parent;

		parent->_right = SubRL;
		if (SubRL)
			SubRL->_parent = parent;

		if (parent2)
		{
			if (parent2->_left == parent)
			{
				parent2->_left = SubR;
			}
			else
			{
				parent2->_right = SubR;
			}
			SubR->_parent = parent2;
		}
		else
		{
			_root = SubR;
			_root->_parent = nullptr;
		}
	}


	Node* Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		//前序创建树
		Node* newRoot = new  Node(root->_data);
		newRoot->_left = Copy(root->_left);
		newRoot->_right = Copy(root->_right);
		return newRoot;
	}
	void Destroy(Node* root)
	{
		if (root == nullptr)
			return;
		//后序毁树
		Destroy(root->_left);
		Destroy(root->_right);

		delete root;
	}
	void _Inorder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		KeyOfT KOT;
		_Inorder(root->_left);
		cout << KOT(root->_data)  << endl;
		_Inorder(root->_right);
	}
private:
	Node* _root;
};

//void TestRBTree1()
//{
//	RBTree<int, int> t;
//	//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
//	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14,18,26,24,31 };
//	for (auto e : a)
//	{
//		/*if (e == 9)
//		{
//			int i = 0;
//		}*/
//
//		t.Insert({ e, e });
//
//		//cout << e << "->" << t.IsBalanceTree() << endl;
//	}
//
//	t.Inorder();
//	cout << t.IsBalance() << endl;
//}
相关推荐
弥琉撒到我14 分钟前
docker对其他中间件镜像拉取多个服务器部署
开发语言·后端·ruby
阿琳a_27 分钟前
通过js实现地理信息坐标WGS84、GCJ-02、BD-09坐标互转
开发语言·javascript·ecmascript
java小吕布31 分钟前
Java Servlet详解:Servlet的生命周期、请求处理与响应发送
java·开发语言·servlet
带多刺的玫瑰1 小时前
Leecode刷题C语言之最少翻转次数使二进制矩阵回文①
c语言·开发语言
fantasy_arch1 小时前
SRT拥塞控制分析
开发语言·网络·php
nece0011 小时前
Acme PHP - Let‘s Encrypt
开发语言·php
玉阳软件yuyangdev_cn2 小时前
嘎嘎快充php版服务端部署配置注意玉阳软件
开发语言·php
宇宙大豹发2 小时前
【Java豆瓣电影爬虫】——抓取电影详情和电影短评数据 -
java·开发语言·数据库·爬虫·python·pycharm·python入门
这猪好帅2 小时前
【项目组件】第三方库——Jsoncpp
服务器·c++·json