map,set的封装

相信大家都对map,set不会陌生,这是非常好用的容器,它的底层是红黑树,红黑树在数据结构中,个人感觉是比较难的一种数据结构,尤其是一会染色,一会旋转的,弄来弄去把人给弄晕了。而我想说的是,红黑树不仅实现难,封装起来也不简单,下面是封装的代码:

#pragma once
#include<iostream>
#include<map>
#include<set>
#include<time.h>
#include<string>
using namespace std;
namespace RB
{
	template<class T, class ref, class ptr>
	struct Iterator;
	enum colous
	{
		RED,
		BLACK
	};
	template<class T>
	struct RbTreeNode
	{
		T _data;
		colous _col = RED;
		RbTreeNode<T>* _left = nullptr;
		RbTreeNode<T>* _right = nullptr;
		RbTreeNode<T>* _parent = nullptr;
		RbTreeNode(const T& x)
			:_data(x)
		{}
	};
	template<class K,class T,class KofT>
	class RbTree
	{
		typedef RbTreeNode<T> node;
		typedef Iterator<T, T&, T*> iterator;
	public:
		void reol(node* parent)
		{
			node* sub = parent->_right;
			node* subl = sub->_left;
			if (_root == parent)
			{
				_root = sub;
				sub->_parent = nullptr;
				sub->_left = parent;
				parent->_parent = sub;
				parent->_right = subl;
				if (subl)
					subl->_parent = parent;
				return;
			}
			node* pparent = parent->_parent;
			if (pparent->_left == parent)
				pparent->_left = sub;
			else
				pparent->_right = sub;
			sub->_parent = pparent;
			sub->_left = parent;
			parent->_parent = sub;
			parent->_right = subl;
			if (subl)
				subl->_parent = parent;
		}
		void reor(node* parent)
		{
			node* sub = parent->_left;
			node* subr = sub->_right;
			if (_root == parent)
			{
				_root = sub;
				sub->_parent = nullptr;
				sub->_right = parent;
				parent->_parent = sub;
				parent->_left = subr;
				if (subr)
					subr->_parent = parent;
				return;
			}
			node* pparent = parent->_parent;
			if (pparent->_left == parent)
				pparent->_left = sub;
			else
				pparent->_right = sub;
			sub->_parent = pparent;
			sub->_right = parent;
			parent->_parent = sub;
			parent->_left = subr;
			if (subr)
				subr->_parent = parent;
		}
		pair<iterator,bool> insert(const T& x)
		{
			if (_root == nullptr)
			{
				_root = new node(x);
				_root->_col = BLACK;
				return make_pair(iterator(_root), true);
			}
			node* parent = nullptr;
			node* cur = _root;
			while (cur)
			{
				parent = cur;
				if (kot(x) < kot(cur->_data))
					cur = cur->_left;
				else if (kot(x) > kot(cur->_data))
					cur = cur->_right;
				else
					return make_pair(iterator(cur), false);
			}
			cur = new node(x);
			if (x < parent->_data)
				parent->_left = cur;
			else
				parent->_right = cur;
			cur->_parent = parent;
			node* grandfather = parent->_parent;
			while (parent && parent->_col != BLACK)
			{
				if (grandfather->_left == parent)
				{
					node* uncle = grandfather->_right;
					//染色
					if (uncle && uncle->_col == RED)
					{
						parent->_col = BLACK;
						uncle->_col = BLACK;
						grandfather->_col = RED;
						if (grandfather == _root)
						{
							grandfather->_col = BLACK;
							break;
						}
					}
					//染色+旋转
					else if (uncle && uncle->_col == BLACK)
					{
						//染色+单旋
						if (parent->_left == cur)
						{
							reor(grandfather);
							grandfather->_col = RED;
							parent->_col = BLACK;
						}
						//染色+双旋
						else
						{
							reol(parent);
							reor(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
					//叔叔节点不存在
					else
					{
						//染色+单旋
						if (parent->_left == cur)
						{
							reor(grandfather);
							grandfather->_col = RED;
							parent->_col = BLACK;
						}
						//染色+双旋
						else
						{
							reol(parent);
							reor(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
				}
				else
				{
					node* uncle = grandfather->_left;
					if (uncle && uncle->_col == RED)
					{
						parent->_col = BLACK;
						uncle->_col = BLACK;
						grandfather->_col = RED;
						if (grandfather == _root)
						{
							grandfather->_col = BLACK;
							break;
						}
					}
					else if (uncle && uncle->_col == BLACK)
					{
						if (parent->_left == cur)
						{
							reor(parent);
							reol(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						else
						{
							reol(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
					//叔叔节点不存在
					else
					{
						//染色+单旋
						if (parent->_left == cur)
						{
							reor(parent);
							reol(grandfather);
							cur->_col = BLACK;
							grandfather->_col = RED;
						}
						//染色+双旋
						else
						{
							reol(grandfather);
							parent->_col = BLACK;
							grandfather->_col = RED;
						}
						break;
					}
				}
				cur = grandfather;
				parent = cur->_parent;
				grandfather = parent->_parent;
			}
			return make_pair(iterator(cur), true);
		}
		iterator find(const K& key)
		{
			if (_root == nullptr)
				return  iterator(nullptr);
			node* cur = _root;
			while (cur)
			{
				if (key < kot(cur->_data))
					cur = cur->_left;
				else if (key > kot(cur->_data))
					cur = cur->_right;
				else
					return iterator(cur);
			}
			return iterator(nullptr);
		}
		iterator begin()
		{
			node* cur = _root;
			while (cur->_left)
				cur = cur->_left;
			return iterator(cur);
		}
		iterator end()
		{
			return iterator(nullptr);
		}
		//下面是测试红黑树是否正确的函数
		/*void print(node* root,int num)
		{
			if (root == nullptr)
			{
				cout << num << endl;
				return;
			}
			if (root->_col == BLACK)
				num++;
			print(root->_left, num);
			print(root->_right, num);
		}
		void prin()
		{
			int num = 0;
			print(_root, num);
		}*/
	private:
		node* _root = nullptr;
		KofT kot;
	};
	template<class T,class ref,class ptr>
	struct Iterator
	{
		typedef RbTreeNode<T> node;
		node* _it;
		Iterator(node* x)
			:_it(x)
		{}
		bool operator!=(const Iterator<T,ref,ptr>& x)const
		{
			return _it != x._it;
		}
		ref operator*()const
		{
			return _it->_data;
		}
		ptr operator->()
		{
			return &_it->_data;
		}
		Iterator<T,ref,ptr>& operator++()
		{
			//右孩子不为空
			if (_it->_right)
			{
				node* cur = _it->_right;
				while (cur->_left)
					cur = cur->_left;
				_it = cur;
				return *this;
			}
			//右孩子为空
			else
			{
				//找父节点不是祖父节点的右孩子的节点
				node* parent = _it->_parent;
				if (parent->_left == _it)
				{
					_it = parent;
					return *this;
				}
				else
				{
					node* pparent = parent->_parent;
					while (pparent)
					{
						if (pparent->_left == parent)
						{
							_it = pparent;
							return *this;
						}
						else
						{
							parent = pparent;
							pparent = pparent->_parent;
						}
					}
					_it = nullptr;
					return *this;					
				}
			}
		}
	};
}

#pragma once
#include "rbtree.h"
namespace cc
{
	//可以写成内部类
	template<class K>
	struct setfunc
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
	template<class K>
	class set
	{
	public:
		typedef RB::RbTreeNode<K> node;
		typedef RB::Iterator<K, K&, K*> iterator;
		pair<iterator,bool> insert(const K& x)
		{
			return Rbtree.insert(x);
		}
		iterator find(const K& key)
		{
			return Rbtree.find(key);
		}
		iterator begin()
		{
			return Rbtree.begin();
		}
		iterator end()
		{
			return Rbtree.end();
		}
	private:
		RB::RbTree<K, K, setfunc<K>> Rbtree;
	};
}
#pragma once
#include "rbtree.h"
namespace cc
{
	//可以写成内部类
	template<class K,class V>
	struct mapfunc
	{
		const K& operator()(const pair<K,V>& key)
		{
			return key.first;
		}
	};
	template<class K,class V>
	class map
	{
	public:
		typedef RB::RbTreeNode<pair<K, V>> node;
		typedef RB::Iterator<pair<K, V>, pair<K, V>&, pair<K, V>*> iterator;
		pair<iterator,bool> insert(const pair<K, V>& x)
		{
			return Rbtree.insert(x);
		}
		iterator find(const K& key)
		{
			return Rbtree.find(key);
		}
		iterator begin()
		{
			return Rbtree.begin();
		}
		iterator end()
		{
			return Rbtree.end();
		}
	    V& operator[](const K& x)
		{
			return Rbtree.insert(make_pair(x, V())).first->second;
		}
	private:
		RB::RbTree<K, pair<K, V>, mapfunc<K,V>> Rbtree;
	};
}
#include"rbtree.h"
#include "map.hpp"
#include "set.h"
void test1()
{
	//RB::RbTree<int> rb;
	//srand(time(0));
	//for (size_t i = 0; i < 100; i++)
	//	rb.insert(rand());
	///*rb.insert(1);
	//rb.insert(2);
	//rb.insert(3);
	//rb.insert(4);
	//rb.insert(5);
	//rb.insert(6);
	//rb.insert(7);
	//rb.insert(8);
	//rb.insert(9);
	//rb.insert(10);*/
	//rb.prin();
}
void test2()
{
	/*cc::map<int, int> m;
	m.insert(make_pair(1, 1));
	m.insert(make_pair(2, 1));
	m.insert(make_pair(3, 1));
	m.insert(make_pair(4, 1));
	m.insert(make_pair(5, 1));
	m.insert(make_pair(6, 1));
	m.insert(make_pair(7, 1));
	m.insert(make_pair(8, 1));
	m.insert(make_pair(9, 1));
	m.insert(make_pair(10, 1));
	m.insert(make_pair(11, 1));
	m.insert(make_pair(12, 1));
	m.insert(make_pair(13, 1));
	m.insert(make_pair(14, 1));
	m.insert(make_pair(15, 1));
	m.find(5);
	cc::map<int, int>::iterator it = m.begin();
	while (it != m.end())
	{
		cout << it->first << endl;
		++it;
	}*/
	cc::map<string, int> m;
	///*int arr[] = { 1,1,1,1,1,1,1,1 };
	//for (auto e : arr)
	//	m[e]++;*/
	string arr[] = { "苹果","香蕉","梨","苹果","香蕉","香蕉" };
	for (auto& e : arr)
		m[e]++;
	//for (auto& e : m)
		//cout << e.first << ":" << e.second << endl;
	auto it = m.begin();
	for (auto& e : m)
		cout << e.first << ":" << e.second << endl;
	
}
void test3()
{
	srand(time(0));
	cc::map<int, int> m;
	for (size_t i = 0; i < 1000; i++)
	{
		static int x = rand() % 1000;
		m[x++]++;
	}
	for (auto& e : m)
		cout << e.first << ":" << e.second << endl;
}
void test4()
{
	cc::set<int> s;
	/*s.insert(1);
	s.insert(2);
	s.insert(3);
	s.insert(5);
	s.insert(2);
	s.insert(10);
	for (auto e : s)
	{
		cout << e << endl;
	}*/
	for (size_t i = 0; i < 1000; i++)
	{
		s.insert(rand());
	}
	for (auto e : s)
		cout << e << endl;
}
int main()
{
	//test1();
	//test2();
	//test3();
	test4();
	return 0;
}

上面是我的封装过程以及代码实现,其实我昨天封装了unordered_map,unordered_set这两个容器,今天封装map,set就感觉简单不少,但是也不是简单。其他的没啥要注意的地方,唯一一个要注意的就是迭代器,迭代器怎么说,还是要动一会脑子的。

首先就是,判断当前节点的右子树是不是空树,如果不是空树的话,那么代表的这个节点以及这个节点的做左子树已经访问完成,而右子树不为空,所还没有访问完这颗树,所以++之后就要找右子树的最左节点。而难得是如果右子树为空的话,那么就代表已经访问完了这课子树的所有节点,所以找他的父节点,而父节点应该已经是被访问了,所以就向上遍历,直到找到父节点不是祖父节点右孩子的节点为止。

这个思想还是有点绕人的,再就是其他的封装,如果看了我上一篇文章内容的伙伴,封装map,set应该还是很简单的。

希望大家支持一下吧!!谢谢!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
SolrTemplate中的query方法返回的结果是List<T>类型,可以通过遍历List来获取每个Document对象,然后再把每个Document对象的字段封装Map集合中。 以下是一个示例代码: ```java List<Map<String, Object>> resultList = new ArrayList<>(); String keyword = "apple"; Query query = new SimpleQuery(new Criteria("title").contains(keyword)); query.setRows(10); // 设置返回结果的最大数量为10 query.setSort(Sort.by("price").ascending()); // 设置按照价格升序排序 query.setFields("id", "title", "price"); // 设置要返回的字段 QueryResponse response = solrTemplate.query(query); for (SolrDocument document : response.getResults()) { Map<String, Object> resultMap = new HashMap<>(); resultMap.put("id", document.get("id")); resultMap.put("title", document.get("title")); resultMap.put("price", document.get("price")); resultList.add(resultMap); } ``` 在上面的代码中,我们先定义了一个List<Map<String, Object>>类型的结果集,然后创建了一个Query对象,设置了查询条件、返回结果数量、排序方式和返回字段等参数。通过调用solrTemplate.query方法执行查询操作,得到QueryResponse对象。然后遍历QueryResponse中的SolrDocument对象,将每个Document对象的id、title、price字段封装Map集合中,最终将Map集合添加到结果集中。 需要注意的是,SolrDocument中的字段值类型可能是Object类型,需要根据实际情况进行类型转换。如果有多个Document对象需要封装,建议使用Java8的Stream API来简化代码。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值