STL——模拟封装map&set

1.底层红黑树结构

为了便于实现map和set,还需对红黑树进行一些改造:

#include<iostream>
using namespace std;
enum Color{RED, BLACK};//节点颜色

template<class T>
struct RBTreeNode {//节点定义
	RBTreeNode(const T& value = T(), Color color = RED)
		: _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _value(value)
		, _color(color)
	{}
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	T _value;
	Color _color;
};

//封装迭代器类
//T-数据类型  Ref-数据引用类型  Ptr-数据指针类型
template<class T, class Ref, class Ptr>
class RBTreeIterator {
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;//迭代器类类型
public:
	RBTreeIterator(Node* pNode = nullptr) 
		: _pNode(pNode)
	{}

	Ref operator*() {
		return _pNode->_value;
	}

	Ptr operator->() {
		//return &(_pNode->_value);
		return &(operator*());
	}

	Self& operator++() {//前置++
		Increament();//加一方法
		return *this;
	}
	Self operator++(int) {//后置++
		Self temp(*this);//加一方法
		Increament();
		return temp;
	}
	Self& operator--() {//前置--
		Decreament();//减一方法
		return *this;
	}
	Self operator--(int) {//后置--
		Self temp(*this);//减一方法
		Decreament();
		return temp;
	}

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

private:
	void Increament() {//++
		//1.右子树存在,找右子树中最左侧的节点
		if (_pNode->_right) {
			_pNode = _pNode->_right;
			while (_pNode->_left) {
				_pNode = _pNode->_left;
			}
		}
		//2.右子树不存在,向上寻找第一个在它右侧的节点
		else {
			Node* parent = _pNode->_parent;
			while (_pNode == parent->_right) {
				_pNode = parent;
				parent = _pNode->_parent;
			}
			//特殊情况,根节点没有右子树
			if (_pNode->_right == parent) return;
			_pNode = parent;
		}
	}

	void Decreament() {//--
		//特殊情况,_pNode初始再head(end)位置
		if (_pNode->_parent->_parent == _pNode && _pNode->_color == RED) {
			_pNode = _pNode->_right;
			return;
		}

		//1.左子树存在,找左子树最右侧的节点
		if (_pNode->_left) {
			_pNode = _pNode->_left;
			while (_pNode->_right) {
				_pNode = _pNode->_right;
			}
		}
		//2.左子树不存在,向上寻找第一个它左侧的节点
		else {
			Node* parent = _pNode->_parent;
			while (_pNode == parent->_left) {
				_pNode = parent;
				parent = _pNode->_parent;
			}
			//因为--最多到begin位置,所以即使根节点没有左子树,也要更新_pNode
			_pNode = parent;
		}
	}

private:
	Node* _pNode;
};

//约定value唯一
//KofT对象获取value的Key
template<class T, class KofT>
class RBTree {
	typedef RBTreeNode<T> Node;
public:
	typedef RBTreeIterator<T, T&, T*> iterator;
public:
	RBTree() 
		: _size(0)
	{
		_head = new Node();
		_head->_left = _head;
		_head->_right = _head;
	}
	~RBTree() {
		Destroy(_head->_parent);
		_size = 0;
		delete _head;
		_head = nullptr;
	}

	//迭代器
	iterator begin() {
		return iterator(_head->_left);
	}
	iterator end() {
		return iterator(_head);
	}

	//交换
	void swap(RBTree<T, KofT>& t) {
		std::swap(_head, t._head);
		std::swap(_size, t._size);
	}

	//清空
	void clear() {
		Destroy(_head->_parent);
		_head->_left = _head;
		_head->_right = _head;
		_size = 0;
	}

	//判空
	bool empty() const {
		return _size == 0;
	}

	//插入
	pair<iterator, bool> Insert(const T& value) {
		Node* newNode = nullptr;
		Node*& root = GetRoot();
		//1.按照二叉搜索树的方式插入
		if (root == nullptr) {//空树
			root = new Node(value, BLACK);
			newNode = root;
			root->_parent = _head;
			_head->_left = root;
			_head->_right = root;
			++_size;
			return make_pair(iterator(newNode), true);
		}
		//查找插入位置
		Node* cur = root;
		Node* parent = cur->_parent;
		KofT koft;
		while (cur) {
			parent = cur;//保存其双亲
			if (koft(value) < koft(cur->_value)) {
				cur = cur->_left;
			}
			else if (koft(value) > koft(cur->_value)) {
				cur = cur->_right;
			}
			else {//已存在
				return make_pair(iterator(cur), false);
			}
		}
		//插入新节点
		cur = new Node(value);//默认插入节点为红色
		newNode = cur;
		if (koft(value) < koft(parent->_value)) {
			parent->_left = cur;
		}
		else {
			parent->_right = cur;
		}
		cur->_parent = parent;
		//2.红黑树性质约束
		while (parent != _head && parent->_color == RED) {//两个红色相连违法规则
			Node* grandFather = parent->_parent;
			if (parent == grandFather->_left) {
				Node* uncle = grandFather->_right;
				//情况一:叔叔节点存在且为红
				if (uncle && uncle->_color == RED) {
					parent->_color = BLACK;
					uncle->_color = BLACK;
					grandFather->_color = RED;
					//改变cur,继续向上调整
					cur = grandFather;
					parent = cur->_parent;
				}
				else {//情况二或三:叔叔节点为空,或叔叔节点存在且为黑
					//因为情况三可以调整为情况二,所有先处理情况三
					if (cur == parent->_right) {
						//将情况三转换为情况二
						RotateLeft(parent);
						std::swap(parent, cur);
					}
					//情况二
					parent->_color = BLACK;
					grandFather->_color = RED;
					RotateRight(grandFather);
				}
			}
			else {//三种情况的对称情况-->解决方法相同
				Node* uncle = grandFather->_left;
				if (uncle && uncle->_color == RED) {//情况一
					parent->_color = BLACK;
					uncle->_color = BLACK;
					grandFather->_color = RED;
					//改变cur,继续向上调整
					cur = grandFather;
					parent = cur->_parent;
				}
				else {//情况二或三
					if (cur == parent->_left) {//情况三
						//调整为情况二
						RotateRight(parent);
						std::swap(cur, parent);
					}
					//情况二
					parent->_color = BLACK;
					grandFather->_color = RED;
					RotateLeft(grandFather);
				}

			}
		}
		//注意:最后根节点可能被调整为了红色,所以需要被改回黑色
		root->_color = BLACK;

		//3.更新头结点左右指针域--插入元素可能改变树的最值
		_head->_left = MostLeft();
		_head->_right = MostRight();
		++_size;
		return make_pair(iterator(newNode), true);
	}

	//查找
	iterator Find(const T& value) {
		KofT koft;
		Node* cur = GetRoot();
		while (cur) {
			if (koft(value) < koft(cur->_value)) {
				cur = cur->_left;
			}
			else if (koft(value) > koft(cur->_value)) {
				cur = cur->_right;
			}
			else {
				return iterator(cur);
			}
		}
		return end();
	}

	//检测是否是红黑树
	bool IsRBTree() {
		Node* root = GetRoot();
		if (root == nullptr) return true;
		if (root->_color == RED) {
			//检测性质2
			std::cout << "FALSE: 根节点为红色!" << std::endl;
			return false;
		}
		int blackCount = 0;
		Node* cur = root;
		while (cur) {//统计一条路径黑色节点个数
			if (cur->_color == BLACK) ++blackCount;
			cur = cur->_left;
		}
		return _IsRBTree(root, blackCount, 0);
	}

	//中序遍历
	void InOrder() {
		_InOrder(GetRoot());
		std::cout << std::endl;
	}
	//获取最值
	int GetMax() {
		return MostRight()->_value;
	}
	int GetMin() {
		return MostLeft()->_value;
	}

private:
	//获取根节点
	Node*& GetRoot() {
		return _head->_parent;
	}
	//获取树的最值节点
	Node* MostLeft() {//最左侧节点
		Node*& root = GetRoot();
		if (root == nullptr) return _head;
		Node* cur = root;
		while (cur->_left) {
			cur = cur->_left;
		}
		return cur;
	}
	Node* MostRight() {//最右侧节点
		Node*& root = GetRoot();
		if (root == nullptr) return _head;
		Node* cur = root;
		while (cur->_right) {
			cur = cur->_right;
		}
		return cur;
	}
	//左单旋
	void RotateLeft(Node* parent) {
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		parent->_right = subRL;
		if (subRL) {//注意subrl可能为空
			subRL->_parent = parent;
		}
		subR->_left = parent;
		//跟新parent和subR的双亲节点
		//先保存好parent原先的双亲节点
		Node* pparent = parent->_parent;
		parent->_parent = subR;
		subR->_parent = pparent;
		//处理上层节点
		if (pparent == _head) {//已经更新到根节点
			_head->_parent = subR;
		}
		else {
			if (parent == pparent->_left) {
				pparent->_left = subR;
			}
			else {
				pparent->_right = subR;
			}
		}
	}
	//右单旋
	void RotateRight(Node* parent) {
		//其思想与左单旋相同
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		parent->_left = subLR;
		if (subLR) {
			subLR->_parent = parent;
		}
		subL->_right = parent;
		Node* pparent = parent->_parent;
		parent->_parent = subL;
		subL->_parent = pparent;
		if (pparent == _head) {
			_head->_parent = subL;
		}
		else {
			if (parent == pparent->_left) {
				pparent->_left = subL;
			}
			else {
				pparent->_right = subL;
			}
		}
	}
	//检测是否满足红黑树特性
	bool _IsRBTree(Node* root, const int blackNum, int count) {
		if (root == nullptr) return true;
		if (root->_color == BLACK) ++count;//统计路径内的黑色节点
		//检测是否满足性质3
		if (root->_parent != _head && root->_color == RED && root->_parent->_color == RED) {
			std::cout << "FALSE: 存在两个相连的红色节点!" << std::endl;
			return false;
		}
		if (root->_left == nullptr && root->_right == nullptr) {
			//是叶子节点,此路径统计结束
			return count == blackNum;//检测性质4
		}
		return _IsRBTree(root->_left, blackNum, count) && _IsRBTree(root->_right, blackNum, count);
	}
	//中序遍历
	void _InOrder(Node*& root) {
		if (root == nullptr) return;
		_InOrder(root->_left);
		std::cout << root->_value << " ";
		_InOrder(root->_right);
	}
	//销毁
	void Destroy(Node* root) {
		if (root == nullptr) return;
		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
		root = nullptr;
	}
private:
	Node* _head;
public:
	size_t _size;
};

2.map封装


#include "RBTree.hpp"
namespace MyMap {
	template<class Key, class T>
	class map {
		typedef pair<Key, T> ValueType;
		struct KofT {//作用:将value的key提取出来
			const Key& operator() (const ValueType& value) {
				return value.first;
			}
		};
		typedef RBTree<ValueType, KofT> Tree;
		/*typedef Tree::iterator iterator;
		上面这种方式,编译器无法确定iterator是Tree中的类型。
		因为静态成员变量也是通过类名::静态成员变量的方式进行访问
		解决方法:用typename显示告诉编译器它是类型*/
		typedef typename Tree::iterator iterator;
	public:
		map()
			: _rbTree()
		{}


		//迭代器
		iterator begin() {
			return _rbTree.begin();
		}
		iterator end() {
			return _rbTree.end();
		}
		//判空
		bool empty() const {
			return _rbTree.empty();
		}
		//容量
		size_t size() const {
			return _rbTree._size;
		}
		void clear() {
			_rbTree.clear();
		}
		//操作
		pair<iterator, bool> insert(const ValueType& value) {
			return _rbTree.Insert(value);
		}
		T& operator[](const Key& key) {
			return (*((insert(make_pair(key, T()))).first)).second;
		}
		void swap(map<Key, T>& m) {
			_rbTree.swap(m._rbTree);
		}
		iterator find(const Key& key) {
			return _rbTree.Find(make_pair(key, T()));
		}
	private:
		Tree _rbTree;
	};
}

3.set封装


#include "RBTree.hpp"
namespace MySet {
	template<class T>
	class set {
		typedef T ValueType;
		struct KofT {
			const T& operator() (const ValueType& value) {
				return value;
			}
		};
		typedef RBTree<ValueType, KofT> Tree;
		typedef typename Tree::iterator iterator;
	public:
		set()
			: _rbTree()
		{}

		//迭代器
		iterator begin() {
			return _rbTree.begin();
		}
		iterator end() {
			return _rbTree.end();
		}
		//判空
		bool empty() const {
			return _rbTree.empty();
		}
		//容量
		size_t size() const {
			return _rbTree._size;
		}
		void clear() {
			_rbTree.clear();
		}
		//操作
		pair<iterator, bool> insert(const ValueType& value) {
			return _rbTree.Insert(value);
		}
		void swap(set<ValueType>& m) {
			_rbTree.swap(m._rbTree);
		}
		iterator find(const T& key) {
			return _rbTree.Find(key);
		}
	private:
		Tree _rbTree;
	};
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hey小孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值