c++--Map和Set的简单封装

1.Map和Set的简单介绍

Map和set没有多大区别,它俩都是键值对容器,即该结构中一般只包含两个成员key,value,key代表键值,value表示与key对应的信息。并且这两个容器为树型结构的关联式容器,这两种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。

Set的介绍:

  •  set是按照一定次序存储元素的容器。
  •  在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的。
  • set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。
  • 在内部,set中的元素总是按照其内部比较对象(类型比较)所指示的特定严格弱排序准则进行排序。
  • set容器通过key访问单个元素的速度通常比unordered_set容器慢,但它们允许根据顺序对子集进行直接迭代。
  • set在底层是用二叉搜索树(红黑树)实现的。

注意:

  • 与map/multimap不同,map/multimap中存储的是真正的键值对<key, value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。
  • set中插入元素时,只需要插入value即可,不需要构造键值对。
  • set中的元素不可以重复(因此可以使用set进行去重)。
  • 使用set的迭代器遍历set中的元素,可以得到有序序列
  • set中的元素默认按照小于来比较
  • set中查找某个元素,时间复杂度为:$log_2 n$
  • set中的元素不允许修改
  • set中的底层使用二叉搜索树(红黑树)来实现

Map的介绍:

  • map是关联容器,它按照特定的次序(按照key来比较)存储由键值key和值value组合而成的元素。
  • 在map中,键值key通常用于排序和惟一地标识元素,而值value中存储与此键值key关联的内容。键值key和值value的类型可能不同,并且在map的内部,key与value通过成员类型
  • value_type绑定在一起,为其取别名称为pair:
  • typedef pair<const key, T> value_type;
  • 在内部,map中的元素总是按照键值key进行比较排序的。
  • map中通过键值访问单个元素的速度通常比unordered_map容器慢,但map允许根据顺序对元素进行直接迭代(即对map中的元素进行迭代时,可以得到一个有序的序列)。
  • map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  •  map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树))。
     

2.Map和Set的实现

由于Map和Set的底层都为红黑树,所以Map和Set的实现通过对红黑树的封装来实现,Set为一个参数,Map为两个参数,所以通过改变模板来实现Map和Set的同时封装。

Set的简单封装:

namespace sss
{

	template<class K>
	class Set
	{
		struct SetKeyofT
		{
			const K& operator()(const K& date)
			{
				return date;
			}
		};	
	public:
		typedef typename RedBlackTree<K, K, SetKeyofT>::iterator iterator;
		iterator begin()
		{
			return _S.begin();
		}
		iterator end()
		{
			return _S.end();
		}

		pair<iterator, bool> Insert(const K& date)
		{
			return _S.insert(date);
		}
	private:
		RedBlackTree<K, K, SetKeyofT> _S;
	};
	//测试用例
	/*void text_set()
	{
		string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
		Set<string> hash;
		for (auto sh : str)
		{
			hash.Insert(sh);
		}
		auto it = hash.begin();
		while (it != hash.end())
		{
			cout << *it << endl;
			++it;
		}

	}*/

}

Map的简单封装

namespace sss
{

	template<class K,class V> 
	class Map
	{
	public:
		struct MapKeyofT
		{
			const K& operator()(const pair<K, V>& date)
			{
				return date.first;
			}
		};
		typedef typename RedBlackTree<K, pair<K, V>, MapKeyofT>::iterator iterator;
		//t//ypedef RedBlackTree<K, pair<K, V>, MapKeyofT> RedBlackTree;
		iterator begin()  
		{
			return _T.begin();
		}
		iterator end()
		{
			return _T.end();
		}

		pair<iterator, bool> Insert(const pair<K,V>& date)
		{
			 return _T.insert(date);
		}

		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = Insert(make_pair(key, V()));
			return ret.first->second;
		}
	private:
		RedBlackTree<K,pair<K,V>, MapKeyofT> _T;
	};


	//测试用例
	//void text_map()
	//{
	//	Map<int, int> hash1;
	//	hash1.Insert(make_pair(1,1));
	//	cout<<hash1[1];
	//	Map<string, int> hash2;
	//	string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
	//	for (auto sh:str)
	//	{
	//		hash2[sh]++;
	//	}
	//	Map<string, int>::iterator it = hash2.begin();
	//	while (it != hash2.end())
	//	{
	//		cout << it->first << ":" << it->second << endl;
	//		++it;
	//	}

	//	for (auto& kv : hash2)
	//	{
	//		cout << kv.first << ":" << kv.second << endl;
	//	}
	//	//hash1 = hash2;
	//	
	//}
}

底层实现:

namespace sss
{
	enum Color
	{
		red,
		black
	};
	template<class T>
	struct RedBlackTreeNode
	{
		RedBlackTreeNode<T>* _left;
		RedBlackTreeNode<T>* _right;
		RedBlackTreeNode<T>* _parent;
		//pair<K, V> _date;
		T _date;
		Color _col;
		RedBlackTreeNode(const T& date=T())
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_date(date)
			//, _col(black)
		{}
	};
	template<class T, class Ref, class Ptr>
	struct __RBTreeIterator
	{
		typedef RedBlackTreeNode<T> Node;
		typedef __RBTreeIterator<T, Ref, Ptr> Self;
		Node* _node;


		__RBTreeIterator(Node* node)
			:_node(node)
		{}


		Ref operator*()
		{
			return _node->_date;
		}
		Ptr operator->()
		{
			return &_node->_date;
		}
		bool operator!=(const Self& _t)
		{
			return _node != _t._node;
		}

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

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

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

	template<class K, class T, class KeyofT>
	class RedBlackTree
	{
		typedef RedBlackTreeNode<T> Node;
	public:		
		typedef __RBTreeIterator<T, T&, T*> iterator;
		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& date)
		{
			KeyofT _com;
			if (_root == nullptr)
			{
				_root = new Node(date);
				_root->_col = black;
				return make_pair(iterator(_root), true);
			}
			Node* parent = nullptr;
			Node* cur = _root;

			while (cur)
			{
				if (_com(cur->_date)< _com(date))
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (_com(cur->_date) > _com(date))
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return make_pair(iterator(cur), false);
				}
			}
			cur = new Node(date);
			cur->_col = red;

			if (_com(parent->_date)  < _com(date))
			{
				parent->_right = cur;
			}
			else 
			{
				parent->_left = cur;
			}
			cur->_parent = parent;
			//Node* uncle=parent->_parent->
			while(parent && parent->_col == red)
			{
				Node* grandfater = parent->_parent;
				assert(grandfater);
				assert(grandfater->_col==black);

				if (parent == grandfater->_left)
				{
					Node* uncle = grandfater->_right;
					// 情况一 : uncle存在且为红,变色+继续往上处理
					if (uncle && uncle->_col == red)
					{
						parent->_col = uncle->_col = black;
						grandfater->_col = red;
						// 继续往上处理
						cur = grandfater;
						parent = cur->_parent;
					}// 情况二+三:uncle不存在 + 存在且为黑
					else
					{
						// 情况二:右单旋+变色
						//     g 
						//   p   u
						// c

						if (cur == parent->_left)
						{
							RotateR(grandfater);
							parent->_col = black;
							grandfater->_col = red;
						}
						else
						{
							// 情况三:左右单旋+变色
							//     g 
							//   p   u
							//     c
							RotateL(parent);
							RotateR(grandfater);
							cur->_col = black;
							grandfater->_col = red;
						}
						break;

					}
				}
				else
				{
					Node* uncle = grandfater->_left;
					// 情况一
					if (uncle && uncle->_col == red)
					{
						parent->_col = uncle->_col = black;
						grandfater->_col = red;
						// 继续往上处理
						cur = grandfater;
						parent = cur->_parent;
					}
					else
					{
						// 情况二:左单旋+变色
						//     g 
						//   u   p
						//         c
						if (cur == parent->_right)
						{
							RotateL(grandfater);
							parent->_col = black;
							grandfater->_col = red;
						}
						else
						{
							// 情况三:右左单旋+变色
							//     g 
							//   u   p
							//     c
							RotateR(parent);
							RotateL(grandfater);
							cur->_col = black;
							grandfater->_col = red;
						}

						break;
					}
				}
			}
			_root->_col = black;
			return make_pair(iterator(cur), true);
		}

		void Inorder()
		{
			_Inorder(_root);
		}
	private:
		//右旋
		void RotateR(Node* parent)
		{
			Node* subl = parent->_left;
			Node* sublr = subl->_right;
			Node* prev = parent->_parent;
			parent->_left = sublr;
			if (sublr)
				sublr->_parent = parent;
			parent->_parent = subl;
			subl->_right = parent;
			if (_root == parent)
			{
				_root = subl;
				subl->_parent = nullptr;
			}
			else
			{
				if (prev->_left == parent)
				{
					subl->_parent = prev;
					prev->_left = subl;
				}
				else
				{
					subl->_parent = prev;
					prev->_right = subl;
				}
			}
		}
		//左旋
		void RotateL(Node* parent)
		{
			Node* subr = parent->_right;
			Node* subrl = subr->_left;
			Node* prev = parent->_parent;

			parent->_right = subrl;
			if (subrl)
				subrl->_parent = parent;
			subr->_left = parent;
			parent->_parent = subr;
			if (_root == parent)
			{
				_root = subr;
				subr->_parent = nullptr;
			}
			else
			{
				if (prev->_left == parent)
				{
					subr->_parent = prev;
					prev->_left = subr;
				}
				else
				{
					subr->_parent = prev;
					prev->_right = subr;
				}
			}
		}

		//遍历
		void _Inorder(Node* _root)
		{
			if (_root == nullptr)
				return;
			_Inorder(_root->_left);
			cout << _root->_date.first << " " << _root->_date.second << endl;
			_Inorder(_root->_right);
		}
	private:
		Node* _root = nullptr;
	};

}

完整代码:

//在不同平台下需加不同头文件
#pragma once
using namespace std;
#include <iostream>
#include <assert.h>
#include "RedBlackTree.h"
#include <string>

namespace sss
{

	template<class K>
	class Set
	{
		struct SetKeyofT
		{
			const K& operator()(const K& date)
			{
				return date;
			}
		};	
	public:
		typedef typename RedBlackTree<K, K, SetKeyofT>::iterator iterator;
		iterator begin()
		{
			return _S.begin();
		}
		iterator end()
		{
			return _S.end();
		}

		pair<iterator, bool> Insert(const K& date)
		{
			return _S.insert(date);
		}
	private:
		RedBlackTree<K, K, SetKeyofT> _S;
	};
	//测试用例
	/*void text_set()
	{
		string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
		Set<string> hash;
		for (auto sh : str)
		{
			hash.Insert(sh);
		}
		auto it = hash.begin();
		while (it != hash.end())
		{
			cout << *it << endl;
			++it;
		}

	}*/

}


namespace sss
{

	template<class K,class V> 
	class Map
	{
	public:
		struct MapKeyofT
		{
			const K& operator()(const pair<K, V>& date)
			{
				return date.first;
			}
		};
		typedef typename RedBlackTree<K, pair<K, V>, MapKeyofT>::iterator iterator;
		//t//ypedef RedBlackTree<K, pair<K, V>, MapKeyofT> RedBlackTree;
		iterator begin()  
		{
			return _T.begin();
		}
		iterator end()
		{
			return _T.end();
		}

		pair<iterator, bool> Insert(const pair<K,V>& date)
		{
			 return _T.insert(date);
		}

		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = Insert(make_pair(key, V()));
			return ret.first->second;
		}
	private:
		RedBlackTree<K,pair<K,V>, MapKeyofT> _T;
	};


	//测试用例
	//void text_map()
	//{
	//	Map<int, int> hash1;
	//	hash1.Insert(make_pair(1,1));
	//	cout<<hash1[1];
	//	Map<string, int> hash2;
	//	string str[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
	//	for (auto sh:str)
	//	{
	//		hash2[sh]++;
	//	}
	//	Map<string, int>::iterator it = hash2.begin();
	//	while (it != hash2.end())
	//	{
	//		cout << it->first << ":" << it->second << endl;
	//		++it;
	//	}

	//	for (auto& kv : hash2)
	//	{
	//		cout << kv.first << ":" << kv.second << endl;
	//	}
	//	//hash1 = hash2;
	//	
	//}
}



namespace sss
{
	enum Color
	{
		red,
		black
	};
	template<class T>
	struct RedBlackTreeNode
	{
		RedBlackTreeNode<T>* _left;
		RedBlackTreeNode<T>* _right;
		RedBlackTreeNode<T>* _parent;
		//pair<K, V> _date;
		T _date;
		Color _col;
		RedBlackTreeNode(const T& date=T())
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_date(date)
			//, _col(black)
		{}
	};
	template<class T, class Ref, class Ptr>
	struct __RBTreeIterator
	{
		typedef RedBlackTreeNode<T> Node;
		typedef __RBTreeIterator<T, Ref, Ptr> Self;
		Node* _node;


		__RBTreeIterator(Node* node)
			:_node(node)
		{}


		Ref operator*()
		{
			return _node->_date;
		}
		Ptr operator->()
		{
			return &_node->_date;
		}
		bool operator!=(const Self& _t)
		{
			return _node != _t._node;
		}

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

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

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

	template<class K, class T, class KeyofT>
	class RedBlackTree
	{
		typedef RedBlackTreeNode<T> Node;
	public:		
		typedef __RBTreeIterator<T, T&, T*> iterator;
		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& date)
		{
			KeyofT _com;
			if (_root == nullptr)
			{
				_root = new Node(date);
				_root->_col = black;
				return make_pair(iterator(_root), true);
			}
			Node* parent = nullptr;
			Node* cur = _root;

			while (cur)
			{
				if (_com(cur->_date)< _com(date))
				{
					parent = cur;
					cur = cur->_right;
				}
				else if (_com(cur->_date) > _com(date))
				{
					parent = cur;
					cur = cur->_left;
				}
				else
				{
					return make_pair(iterator(cur), false);
				}
			}
			cur = new Node(date);
			cur->_col = red;

			if (_com(parent->_date)  < _com(date))
			{
				parent->_right = cur;
			}
			else 
			{
				parent->_left = cur;
			}
			cur->_parent = parent;
			//Node* uncle=parent->_parent->
			while(parent && parent->_col == red)
			{
				Node* grandfater = parent->_parent;
				assert(grandfater);
				assert(grandfater->_col==black);

				if (parent == grandfater->_left)
				{
					Node* uncle = grandfater->_right;
					// 情况一 : uncle存在且为红,变色+继续往上处理
					if (uncle && uncle->_col == red)
					{
						parent->_col = uncle->_col = black;
						grandfater->_col = red;
						// 继续往上处理
						cur = grandfater;
						parent = cur->_parent;
					}// 情况二+三:uncle不存在 + 存在且为黑
					else
					{
						// 情况二:右单旋+变色
						//     g 
						//   p   u
						// c

						if (cur == parent->_left)
						{
							RotateR(grandfater);
							parent->_col = black;
							grandfater->_col = red;
						}
						else
						{
							// 情况三:左右单旋+变色
							//     g 
							//   p   u
							//     c
							RotateL(parent);
							RotateR(grandfater);
							cur->_col = black;
							grandfater->_col = red;
						}
						break;

					}
				}
				else
				{
					Node* uncle = grandfater->_left;
					// 情况一
					if (uncle && uncle->_col == red)
					{
						parent->_col = uncle->_col = black;
						grandfater->_col = red;
						// 继续往上处理
						cur = grandfater;
						parent = cur->_parent;
					}
					else
					{
						// 情况二:左单旋+变色
						//     g 
						//   u   p
						//         c
						if (cur == parent->_right)
						{
							RotateL(grandfater);
							parent->_col = black;
							grandfater->_col = red;
						}
						else
						{
							// 情况三:右左单旋+变色
							//     g 
							//   u   p
							//     c
							RotateR(parent);
							RotateL(grandfater);
							cur->_col = black;
							grandfater->_col = red;
						}

						break;
					}
				}
			}
			_root->_col = black;
			return make_pair(iterator(cur), true);
		}

		void Inorder()
		{
			_Inorder(_root);
		}
	private:
		//右旋
		void RotateR(Node* parent)
		{
			Node* subl = parent->_left;
			Node* sublr = subl->_right;
			Node* prev = parent->_parent;
			parent->_left = sublr;
			if (sublr)
				sublr->_parent = parent;
			parent->_parent = subl;
			subl->_right = parent;
			if (_root == parent)
			{
				_root = subl;
				subl->_parent = nullptr;
			}
			else
			{
				if (prev->_left == parent)
				{
					subl->_parent = prev;
					prev->_left = subl;
				}
				else
				{
					subl->_parent = prev;
					prev->_right = subl;
				}
			}
		}
		//左旋
		void RotateL(Node* parent)
		{
			Node* subr = parent->_right;
			Node* subrl = subr->_left;
			Node* prev = parent->_parent;

			parent->_right = subrl;
			if (subrl)
				subrl->_parent = parent;
			subr->_left = parent;
			parent->_parent = subr;
			if (_root == parent)
			{
				_root = subr;
				subr->_parent = nullptr;
			}
			else
			{
				if (prev->_left == parent)
				{
					subr->_parent = prev;
					prev->_left = subr;
				}
				else
				{
					subr->_parent = prev;
					prev->_right = subr;
				}
			}
		}

		//遍历
		void _Inorder(Node* _root)
		{
			if (_root == nullptr)
				return;
			_Inorder(_root->_left);
			cout << _root->_date.first << " " << _root->_date.second << endl;
			_Inorder(_root->_right);
		}
	private:
		Node* _root = nullptr;
	};

}

猜你喜欢

转载自blog.csdn.net/weixin_66828150/article/details/132384399
今日推荐