map和set的封装细节

目录

一,红黑树部分

1.模板参数​编辑

2.节点插入部分

3.验证树是否是红黑树

4.旋转实现

二,迭代器部分

1.前置加加的实现

2.保证set和map对应的Key不能被修改。

3.map方括号的实现

三,封装源码


一,红黑树部分

1.模板参数

K为find是通过K的类型去查找,T为红黑树中节点的类型,KeyOFT为比较插入时需要拿到T中的KEY参数。

如何实现KeyOFT仿函数 细节:

在MySet类中,我们知道此时的节点为单参数Key,所以直接返回值就可以。

在MyMap类中,我们知道此时的节点为一个pair,所以返回pair的第一个参数用作比较插入。

2.节点插入部分

细节:看代码注释

std::pair<Iterator,bool> insert(const T& t) {
			if (_root == nullptr) {
				_root = new Node(t);
				return std::make_pair(_root,true);
			}
			KeyOFT kot;
			Node* parent = _root;
			Node* cur = _root;
			while (cur) {
				if (kot(cur->_data) > kot(t)) {
					parent = cur;
					cur = cur->_left;
				}
				else if (kot(cur->_data) < kot(t)) {
					parent = cur;
					cur = cur->_right;
				}
				else {
					return std::make_pair(cur, false);
				}
			}
			cur = new Node(t);
			Node* recur = cur;
			if (kot(t) < kot(parent->_data)) {
				parent->_left = cur;
				cur->_parent = parent;
			}
			else if (kot(t) > kot(parent->_data)) {
				parent->_right = cur;
				cur->_parent = parent;
			}
			else {
				return std::make_pair(cur, false);
			}
			while (parent && parent->_col == RED) {
				Node* grandFather = parent->_parent;
				if (grandFather == nullptr) {
					break;
				}
				if (grandFather&&parent == grandFather->_left) {
					//    g
					//  p   u
					Node* uncle = grandFather->_right;
					//叔叔存在且为红,只需向上变色即可
					if (uncle && uncle->_col == RED) {
						parent->_col = BLACK;
						uncle->_col = BLACK;
						grandFather->_col = RED;
						//继续向上处理
						cur = grandFather;
						parent = grandFather->_parent;
					}
					//叔叔不存在或者为黑,需要旋转,不需要再向上处理
					else {
						if (cur == parent->_left) {
							//    g
							//  p   u
							//c
							RotateR(grandFather);
							parent->_col = BLACK;
							grandFather->_col = RED;
							break;
						}
						else if (cur == parent->_right){
							//    g
							//  p   u
							//   c
							RotateL(parent);
							RotateR(grandFather);
							cur->_col = BLACK;
							parent->_col = RED;
							grandFather->_col = RED;
							break;
						}
						else {
							assert(false);
						}
					}
				}
				else if (grandFather && parent == grandFather->_right) {
					//    g
					//  u   p
					Node* uncle = grandFather->_left;
					//叔叔存在且为红,只需向上变色即可
					if (uncle && uncle->_col == RED) {
						parent->_col = BLACK;
						uncle->_col = BLACK;
						grandFather->_col = RED;
						//继续向上处理
						cur = grandFather;
						parent = grandFather->_parent;
					}
					//叔叔不存在或者为黑,需要旋转,不需要再向上处理
					else {
						if (cur == parent->_left) {
							//    g
							//  u   p
							//    c
							RotateR(parent);
							RotateL(grandFather);
							parent->_col = RED;
							grandFather->_col = RED;
							cur->_col = BLACK;
							break;
						}
						else if (cur == parent->_right) {
							//    g
							//  u   p
							//        c
							RotateL(grandFather);
							parent->_col = BLACK;
							grandFather->_col = RED;
							break;
						}
						else {
							assert(false);
						}
					}
				}
				else {
					assert(false);
				}
			}
            //保证根节点为黑
			_root->_col = BLACK;
			return std::make_pair(recur, true);
		}

3.验证树是否是红黑树

以接口的形式提供给外部,因为外部拿不到根节点。

细节:

先将一条路走到底,然后返回一共有多少黑节点,将此数据作为参考数据,然后遍历整棵树走到空的时候,对比参考数据,不相等则违反了每条路径的黑节点相等规则。

在遍历树的过程中,如果父节点和子节点都为红节点,则违反了红节点不相邻规则

4.旋转实现

细节图在往期中有画,这里附上源码

void RotateL(Node* parent) {
			Node* nodeR = parent->_right;
			Node* nodeRL = nodeR->_left;
			if (nodeRL) {
				nodeRL->_parent = parent;
			}
			Node* ppNode = parent->_parent;
			if (ppNode) {
				if (ppNode->_left == parent) {
					ppNode->_left = nodeR;
					nodeR->_parent = ppNode;
				}
				else {
					ppNode->_right = nodeR;
					nodeR->_parent = ppNode;
				}
			}
			else {
				_root = nodeR;
				nodeR->_parent = nullptr;
			}
			nodeR->_left = parent;
			parent->_right = nodeRL;
			parent->_parent = nodeR;
		}
		void RotateR(Node* parent) {
			Node* nodeL = parent->_left;
			Node* nodeLR = nodeL->_right;
			if (nodeLR) {
				nodeLR->_parent = parent;
			}
			Node* ppNode = parent->_parent;
			if (ppNode) {
				if (ppNode->_left == parent) {
					nodeL->_parent = ppNode;
					ppNode->_left = nodeL;
				}
				else {
					nodeL->_parent = ppNode;
					ppNode->_right = nodeL;
				}
			}
			else {
				_root = nodeL;
				nodeL->_parent = nullptr;
			}
			parent->_left = nodeLR;
			parent->_parent = nodeL;
			nodeL->_right = parent;
		}

二,迭代器部分

1.前置加加的实现

细节;

当此节点的右节点不为空时,找到右子树的最左节点,此时为当前节点的下一个节点

当右节点为空时,此时以此节点为根的整棵树都遍历完成,这是向上找到parent左边为cur的parent节点,此时parent为下一个需遍历节点。

注:减减逻辑与加加相反,这里不多加赘述,后置加加与减减直接复用前置的代码即可实现,封装源码部分有实现哦

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

2.保证set和map对应的Key不能被修改。

细节:封装时传入对应的节点参数使用const修饰

3.map方括号的实现

细节:

调用insert函数,insert返回一个pair,pair第一个参数为指向节点的迭代器,因为重载了-> ,所以迭代器调用second——首先调用->函数找到pair的地址,再去找到second,因为第二个参数可以修改,所以返回second的引用

三,封装源码

这里附上封装源码,分为四个文件进行封装

#pragma once
#include<assert.h>
#include<iostream>
namespace yuan {
	enum Colour {
		RED,
		BLACK
	};
	template<class T>
	struct RBNode {
		typedef RBNode<T> Node;
		Node* _left;
		Node* _right;
		Node* _parent;
		T _data;
		Colour _col ;
		RBNode(const T& data)
			:_left(nullptr)
			, _right(nullptr)
			, _parent(nullptr)
			, _data(data)
			, _col(RED)
		{}
	};
	template<class T,class Ref, class Ptr>
	struct IteratorRBtree {
		typedef IteratorRBtree<T,  Ref, Ptr> self;
		typedef RBNode<T> Node;
		Node* _node;
		IteratorRBtree(Node* node)
			:_node(node)
		{}
		Ptr operator->() {
			return &_node->_data;
		}
		Ref operator*() {
			return _node->_data;
		}
		bool operator!=(const self& s) {
			return _node != s._node;
		}
		self& operator++() {
			if (_node->_right) {
				Node* rightNode = _node->_right;
				Node* LeftMinNode = rightNode;
				while (LeftMinNode->_left) {
					LeftMinNode = LeftMinNode->_left;
				}
				_node = LeftMinNode;
			}
			else{
				Node* parent = _node->_parent;
				Node* cur = _node;
				while (parent && parent->_right == cur) {
					cur = parent;
					parent = parent->_parent;
				}
				_node = parent;
			}
			return *this;
		}
		self operator++(int) {
			self temp(this->_node);
			++(*this);
			return temp;
		}
	};
	template<class K,class T,class KeyOFT>
	class RBTree {
	public:
		typedef RBNode<T> Node;
		typedef IteratorRBtree<T, T&, T*> Iterator;
		typedef IteratorRBtree<T, const T&, const T*> const_Iterator;
		Iterator begin() {
			Node* cur = _root;
			while (cur->_left) {
				cur = cur->_left;
			}
			return cur;
		}
		Iterator end() {
			return nullptr;
		}
		const_Iterator end() const{
			return nullptr;
		}
		const_Iterator begin() const {
			Node* cur = _root;
			while (cur->_left) {
				cur = cur->_left;
			}
			return cur;
		}
		
		Iterator find(const K& t) {
			KeyOFT kot;
			Node* cur = _root;
			while (cur) {
				if (kot(cur->_data) > t) {
					cur = cur->_left;
				}
				else if (kot(cur->_data) < t) {
					cur = cur->_right;
				}
				else {
					return cur;
				}
			}
			return nullptr;
		}
		std::pair<Iterator,bool> insert(const T& t) {
			if (_root == nullptr) {
				_root = new Node(t);
				return std::make_pair(_root,true);
			}
			KeyOFT kot;
			Node* parent = _root;
			Node* cur = _root;
			while (cur) {
				if (kot(cur->_data) > kot(t)) {
					parent = cur;
					cur = cur->_left;
				}
				else if (kot(cur->_data) < kot(t)) {
					parent = cur;
					cur = cur->_right;
				}
				else {
					return std::make_pair(cur, false);
				}
			}
			cur = new Node(t);
			Node* recur = cur;
			if (kot(t) < kot(parent->_data)) {
				parent->_left = cur;
				cur->_parent = parent;
			}
			else if (kot(t) > kot(parent->_data)) {
				parent->_right = cur;
				cur->_parent = parent;
			}
			else {
				return std::make_pair(cur, false);
			}
			while (parent && parent->_col == RED) {
				Node* grandFather = parent->_parent;
				if (grandFather == nullptr) {
					break;
				}
				if (grandFather&&parent == grandFather->_left) {
					//    g
					//  p   u
					Node* uncle = grandFather->_right;
					//叔叔存在且为红,只需向上变色即可
					if (uncle && uncle->_col == RED) {
						parent->_col = BLACK;
						uncle->_col = BLACK;
						grandFather->_col = RED;
						//继续向上处理
						cur = grandFather;
						parent = grandFather->_parent;
					}
					//叔叔不存在或者为黑,需要旋转,不需要再向上处理
					else {
						if (cur == parent->_left) {
							//    g
							//  p   u
							//c
							RotateR(grandFather);
							parent->_col = BLACK;
							grandFather->_col = RED;
							break;
						}
						else if (cur == parent->_right){
							//    g
							//  p   u
							//   c
							RotateL(parent);
							RotateR(grandFather);
							cur->_col = BLACK;
							parent->_col = RED;
							grandFather->_col = RED;
							break;
						}
						else {
							assert(false);
						}
					}
				}
				else if (grandFather && parent == grandFather->_right) {
					//    g
					//  u   p
					Node* uncle = grandFather->_left;
					//叔叔存在且为红,只需向上变色即可
					if (uncle && uncle->_col == RED) {
						parent->_col = BLACK;
						uncle->_col = BLACK;
						grandFather->_col = RED;
						//继续向上处理
						cur = grandFather;
						parent = grandFather->_parent;
					}
					//叔叔不存在或者为黑,需要旋转,不需要再向上处理
					else {
						if (cur == parent->_left) {
							//    g
							//  u   p
							//    c
							RotateR(parent);
							RotateL(grandFather);
							parent->_col = RED;
							grandFather->_col = RED;
							cur->_col = BLACK;
							break;
						}
						else if (cur == parent->_right) {
							//    g
							//  u   p
							//        c
							RotateL(grandFather);
							parent->_col = BLACK;
							grandFather->_col = RED;
							break;
						}
						else {
							assert(false);
						}
					}
				}
				else {
					assert(false);
				}
			}
			_root->_col = BLACK;
			return std::make_pair(recur, true);
		}
		bool TestTree() {
			int refNum = 0;
			Node* cur = _root;
			while (cur) {
				if (cur->_col == BLACK) {
					refNum++;
				}
				cur = cur->_left;
			}
			return _TestTree(_root, refNum,0);
		}
	private:
		bool _TestTree(Node* root,int refNum,int BlackNum) {
			if (root == nullptr) {
				if (refNum != BlackNum) {
					std::cout << "存在黑色节点的数量不相等的路径" << std::endl;
					return false;
				}
				return true;
			}
			if (root->_col == BLACK) {
				BlackNum++;
			}
			if (root->_parent && root->_parent->_col == RED && root->_col == RED) {
				std::cout << "存在连续红节点" << std::endl;
				return false;
			}
			return _TestTree(root->_left, refNum, BlackNum)
				&& _TestTree(root->_right, refNum, BlackNum);
		}
		Node* _root = nullptr;
		void RotateL(Node* parent) {
			Node* nodeR = parent->_right;
			Node* nodeRL = nodeR->_left;
			if (nodeRL) {
				nodeRL->_parent = parent;
			}
			Node* ppNode = parent->_parent;
			if (ppNode) {
				if (ppNode->_left == parent) {
					ppNode->_left = nodeR;
					nodeR->_parent = ppNode;
				}
				else {
					ppNode->_right = nodeR;
					nodeR->_parent = ppNode;
				}
			}
			else {
				_root = nodeR;
				nodeR->_parent = nullptr;
			}
			nodeR->_left = parent;
			parent->_right = nodeRL;
			parent->_parent = nodeR;
		}
		void RotateR(Node* parent) {
			Node* nodeL = parent->_left;
			Node* nodeLR = nodeL->_right;
			if (nodeLR) {
				nodeLR->_parent = parent;
			}
			Node* ppNode = parent->_parent;
			if (ppNode) {
				if (ppNode->_left == parent) {
					nodeL->_parent = ppNode;
					ppNode->_left = nodeL;
				}
				else {
					nodeL->_parent = ppNode;
					ppNode->_right = nodeL;
				}
			}
			else {
				_root = nodeL;
				nodeL->_parent = nullptr;
			}
			parent->_left = nodeLR;
			parent->_parent = nodeL;
			nodeL->_right = parent;
		}
		/*void _order(Node* root) {
			if (root == nullptr) {
				return;
			}
			_order(root->_left);
			std::cout << root->_data << " ";
			_order(root->_right);
		}*/
	};
}


#pragma once
#include"Encapsulation_of_Map_and_Set.h"
using namespace yuan;
template<class T>
class MySet {
public:
	struct KeyOFSet {
		const T& operator()(const T& Key) {
			return Key;
		}
	};
	typedef typename RBTree<T, const T, KeyOFSet>::Iterator iterator;
	iterator begin() {
		return _root.begin();
	}
	iterator end() {
		return _root.end();
	}
	std::pair<iterator, bool> insert(const T& t) {
		return _root.insert(t);
	}
	iterator find(const T& t) {
		return _root.find(t);
	}
	bool testTree() {
		return _root.TestTree();
	}
private:
	RBTree<T,const T, KeyOFSet> _root;
};



#pragma once
#include"Encapsulation_of_Map_and_Set.h"
using namespace yuan;
template<class K,class V>
class MyMap {
	struct KeyOFMAP {
		const K& operator()(const std::pair<K, V>& p) {
			return p.first;
		}
	};
public:
		typedef typename RBTree<K, std::pair<const K, V>, KeyOFMAP>::Iterator iterator;
		iterator begin() {
			return _root.begin();
		}
		iterator end() {
			return _root.end();
		}
		std::pair<iterator,bool> insert(const std::pair<const K, V>& p) {
			return _root.insert(p);
		}
		iterator find(const K& t) {
			return _root.find(t);
		}
		V& operator[](const K& k) {
			std::pair<iterator,bool> temp=_root.insert(std::make_pair(k, V()));
			return temp.first->second;
		}
		bool testTree() {
			return _root.TestTree();
		}
private:
	RBTree<K, std::pair<const K, V>, KeyOFMAP> _root;
};



#include"Encapsulation_of_Map_and_Set.h"
#include"MySet.h"
#include"MyMap.h"
using namespace yuan;
void testSet() {
	MySet<int> s;
	s.insert(4);
	std::cout << s.testTree() << std::endl;
	s.insert(2);
	std::cout << s.testTree() << std::endl;
	s.insert(5);
	std::cout << s.testTree() << std::endl;
	s.insert(15);
	std::cout << s.testTree() << std::endl;
 	s.insert(7);
	std::cout << s.testTree() << std::endl;
	s.insert(1);
	std::cout << s.testTree() << std::endl;
	s.insert(5);
	std::cout << s.testTree() << std::endl;
	s.insert(7);
	MySet<int>::iterator it = s.begin();
	/*while (it != s.end()) {
		std::cout << *it << " ";
		++it;
	}*/
	/*for (int i = 0; i < 1000; i++) {
		
		std::cout << i << "->" << s.testTree() << std::endl;
	}*/
	std::cout << s.testTree() << std::endl;
}
void testMap() {
	MyMap<int, int> m1;
	std::srand(time(0));
	int temp;
	for (int i = 0; i < 10; i++) {
		temp = i + rand();
		m1[temp] = rand();
		//std::cout <<i<<"->"<< m1.testTree()<<std::endl;
	}
	MyMap<int, int>::iterator it = m1.begin();
	while (it != m1.end()) {
		if (it->first == 9) {
			int s = 0;
		}
		std::cout << it->first << " " << it->second << std::endl;
		it++;
	}
	///*++it;
	//std::cout<<m1.find(3)->second;*/
	//std::cout << m1[9] << std::endl; i << "->" 
	//std::cout << m1.testTree() << std::endl;
}
int main() {
	testMap();
	return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值