STL——map和set模拟实现

map和set的底层是使用红黑树来实现的,接下来我利用红黑树来模拟实现一下map和set。
map详解博客链接:https://blog.youkuaiyun.com/smx_dd/article/details/86531881
set详解博客链接:https://blog.youkuaiyun.com/smx_dd/article/details/86555973
红黑树详解与实现博客链接:https://blog.youkuaiyun.com/smx_dd/article/details/86632066

首先因为关联式容器中存储的是键值对,我们需要对之前实现的红黑树进行改造。
修改模板参数:template<class K,class ValueType,class KeyOfValue>
1. K代表key的类型
2. ValueType如果是map则表示键值对pair<K,V>;如果是set则表示K。
3. KeyOfValue:是通过ValueType获取Key值的一个仿函数类,因为我们在进行插入操作需要比较大小时,操作的是键值对无法直接比较大小,需要通过仿函数来获取要比较大小的值(key)来比较大小,仿函数就是在类中重载operator()函数,这样我们可以通过:类名+(),即创建一个该类的临时对象,通过该临时对象去访问operator(),从而可以将类当做函数一样来使用。

改造后的红黑树代码:MyRBTree.h

#pragma once
#include<iostream>
#include<string>
using namespace std;
enum Color
{
	RED,
	BLACK,
};
template<class T>
struct RBNode
{
	RBNode<T>* left;
	RBNode<T>* right;
	RBNode<T>* parent;
	T val;
	Color color;
	RBNode(const T& value = T(), Color _color = RED)
		:left(nullptr)
		, right(nullptr)
		, parent(nullptr)
		, val(value)
		, color(_color)
	{}
};
template<class T>
class Iterator
{
	typedef RBNode<T> Node;
public:
	Iterator(Node* _node = nullptr)
		:pNode(_node)
	{}
	Iterator(const Iterator& it)
		:pNode(it.pNode)
	{}
	T& operator*()
	{
		return pNode->val;
	}
	T* operator->()
	{
		return &(operator*());
	}
	Iterator<T>& operator++()
	{
		increasement();
		return *this;
	}
	Iterator<T>& operator++(int)
	{
		Iterator<T> temp(*this);
		increasement();
		return temp;

	}
	Iterator<T>& operator--()
	{
		decreasement();
		return *this;
	}
	Iterator<T>& operator--(int)
	{
		Iterator<T> temp(*this);
		decreasement();
		return temp;
	}
	bool operator!=(const Iterator& it)
	{
		return pNode != it.pNode;
	}
	bool operator==(const Iterator& it)
	{
		return pNode == it.pNode;
	}
private:
	void increasement()
	{
		if (pNode->right)
		{
			pNode = pNode->right;
			while (pNode->left)
			{
				pNode = pNode->left;
			}
		}
		else
		{
			Node* pParent = pNode->parent;
			while (pParent->right == pNode)
			{
				pNode = pParent;
				pParent = pParent->parent;
			}
			if (pNode->right != pParent)
			{
				pNode = pParent;
			}
		}
	}
	void decreasement()
	{
		if (pNode->parent->parent == pNode&&pNode->color == RED)
		{
			pNode = pNode->right;
		}
		else if (pNode->right)
		{
			pNode = pNode->left;
			while (pNode->right)
			{
				pNode = pNode->right;
			}
		}
		else
		{
			Node* pParent = pNode->parent;
			while (pParent->left == pNode)
			{
				pNode = pParent;
				pParent = pParent->parent;
			}
			pNode = pParent;
		}
	}
	Node* pNode;
};

template<class K, class T,class KeyOfVlaue>
class RBTree
{
public:
	typedef RBNode<T> Node;
	typedef Iterator<T> _iterator;
	_iterator begin()
	{
		return _iterator(header->left);
	}
	_iterator end()
	{
		return _iterator(header);
	}
	RBTree()
	{
		header = new Node;
		header->parent = nullptr;
		header->left = header;
		header->right = header;
	}
	pair<_iterator, bool> insert(const T& value)
	{
		if (header->parent == nullptr)
		{
			Node* root = new Node(value, BLACK);
			root->parent = header;
			header->left = root;
			header->right = root;
			header->parent = root;
			return make_pair(_iterator(root), true);
		}
		KeyOfVlaue keyofvalue;

		Node* parent = nullptr;
		Node* root = header->parent;
		Node* cur = root;
		while (cur)
		{
			if (keyofvalue(cur->val) > keyofvalue(value))
			{
			parent = cur;
			cur = cur->left;
			}
			else if (keyofvalue(cur->val) < keyofvalue(value))
			{
			parent = cur;
			cur = cur->right;
			}
			else
			{
				return make_pair(_iterator(cur), false);
			}
		}
		cur = new Node(value, RED);
		Node* newNode = cur;
		if (keyofvalue(parent->val) > keyofvalue(cur->val))
		{
		parent->left = cur;
		cur->parent = parent;
		}
		else
		{
			parent->right = cur;
			cur->parent = parent;
		}
		while (cur != root&&cur->parent->color == RED)
		{
			parent = cur->parent;
			Node* grandpa = parent->parent;
			if (grandpa->left == parent)
			{
				Node* uncle = grandpa->right;
				if (uncle&&uncle->color == RED)
				{
					parent->color = BLACK;
					uncle->color = BLACK;
					grandpa->color = RED;
					cur = grandpa;
				}
				else
				{
					if (cur == parent->right)
					{
						rotateL(parent);
						swap(parent, cur);
					}
					rotateR(grandpa);
					parent->color = BLACK;
					grandpa->color = RED;
					break;
				}
			}
			else
			{
				Node* uncle = grandpa->left;
				if (uncle&&uncle->color == RED)
				{
					parent->color = BLACK;
					uncle->color = BLACK;
					grandpa->color = RED;
					cur = grandpa;
				}
				else
				{
					if (cur == parent->left)
					{
						rotateR(parent);
						swap(parent, cur);
					}
					rotateL(grandpa);
					parent->color = BLACK;
					grandpa->color = RED;
					break;
				}
			}
		}

		header->parent->color = BLACK;
		header->left = LeftMost();
		header->right = RightMost();

		return make_pair(_iterator(newNode), true);
	}
	void rotateR(Node* parent)
	{
		Node* subL = parent->left;
		Node* subLR = subL->right;
		parent->left = subLR;
		if (subLR)
		{
			subLR->parent = parent;
		}
		subL->right = parent;

		Node* grandpa = parent->parent;
		parent->parent = subL;
		if (header->parent == parent)
		{
			header->parent = subL;
			subL->parent = header;
		}
		else
		{
			if (grandpa->left == parent)
			{
				grandpa->left = subL;
			}
			else
			{
				grandpa->right = subL;
			}
			subL->parent = grandpa;
		}
	}
	void rotateL(Node* parent)
	{
		Node* subR = parent->right;
		Node* subRL = subR->left;

		parent->right = subRL;
		if (subRL)
		{
			subRL->parent = parent;
		}
		subR->left = parent;
		Node* grandpa = parent->parent;
		parent->parent = subR;
		if (header->parent == parent)
		{
			header->parent = subR;
			subR->parent = header;
		}
		else
		{
			if (grandpa->left == parent)
			{
				grandpa->left = subR;
			}
			else
			{
				grandpa->right = subR;
			}
			subR->parent = grandpa;
		}
	}
	Node* LeftMost()
	{
		Node* cur = header->parent;
		if (nullptr == cur)
		{
			return header;
		}
		while (cur->left)
		{
			cur = cur->left;
		}
		return cur;
	}
	Node* RightMost()
	{
		Node* cur = header->parent;
		if (nullptr == cur)
		{
			return header;
		}
		while (cur->right)
		{
			cur = cur->right;
		}
		return cur;
	}
	void inorder()
	{
		_inorder(header->parent);
		cout << endl;
	}
	bool empty()
	{
		return header->parent == nullptr;
	}
	bool IsValidRBTree()
	{
		Node* root = header->parent;
		if (root == nullptr)
		{
			return true;
		}
		if (BLACK != root->color)
		{
			cout << "不满足根结点为黑色!" << endl;
			return false;
		}
		size_t blackcount = 0;
		Node* cur = root;
		while (cur)
		{
			if (cur->color == BLACK)
			{
				++blackcount;
			}
			cur = cur->left;
		}
		size_t k = 0;
		_IsValidRBTree(root, k, blackcount);
	}
private:
	Node* header;
	void _inorder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_inorder(root->left);
		cout << root->val << " ";
		_inorder(root->right);
	}
	bool _IsValidRBTree(Node* root, size_t k, size_t blackcount)
	{
		if (nullptr == root)
		{
			return true;
		}
		if (BLACK == root->color)
		{
			++k;
		}
		Node* pParent = root->parent;
		if (pParent&&pParent->color == RED&&root->color == RED)
		{
			cout << "不满足不存在两个连接的红色节点!" << endl;
			return false;
		}
		if (nullptr == root->left&&nullptr == root->right)
		{
			if (k != blackcount)
			{
				cout << "不满足每条路径上黑色节点个数相同!" << endl;
				return false;
			}
		}
		return _IsValidRBTree(root->left, k, blackcount) && _IsValidRBTree(root->right, k, blackcount);
	}
};

map模拟实现:mymap.h

#include"MyRBTree.h"


	template<class K, class V>
	class map
	{
		class KeyOfValue   //该内部类的作用是获取键值对的key值(仿函数类)
		{
		public:
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<K, V>, KeyOfValue>::_iterator iterator;

		iterator begin()
		{
			return tree.begin();
		}
		iterator end()
		{
			return tree.end();
		}
		bool empty() const
		{
			return tree.empty();
		}
		V& operator[](const K& key)
		{
			return (*(tree.insert(make_pair(key, V()))).first).second;
		}
		pair<iterator, bool> insert(const pair<K, V>& kv)
		{
			return tree.insert(kv);
		}
	private:
		RBTree<K, pair<K, V>, KeyOfValue> tree;
	};

	void testmap()
	{
		map<int, string> m;
		
		m.insert(make_pair(3, "three"));
		m.insert(make_pair(5, "five"));
		m.insert(make_pair(4, "four"));
		m.insert(make_pair(1, "one"));
		m.insert(make_pair(2, "two"));

		map<int, string>::iterator it = m.begin();
		while (it != m.end())
		{
			cout << (*it).first << "-->" << (*it).second << "  ";
			cout << it->first << "-->" << it->second << endl;
			it++;
		}

		m[6];
		m[7] = "seven";

		it = m.begin();
		while (it != m.end())
		{
			cout << (*it).first << "-->" << (*it).second << "  ";
			cout << it->first << "-->" << it->second << endl;
			it++;
		}
		cout << m[4] << endl;
	}

map的一个特点就是重载了 operator[] 函数,而该函数的原理是,先插入,然后返回 value 值。
1. 我们先利用底层红黑树的插入,将键值对插入进去:tree.insert(make_pair(key,V()))
2. 红黑树的插入函数insert()返回的是pair<iterator,bool>键值对,该键值对的first值是一个迭代器,也就是键值对pair<key,value>的位置:  (tree.insert(make_pair(key,V()))).first
3. 我们只要取出该键值对的second值,就是我们想要的value值: (*(tree.insert(make_pair(key,V()))).first).second

set的模拟实现:myset.h

set的模拟实现与map类似,只是没有重载 operator[] 函数,而且插入的只是一个key值
 

#include"MyRBTree.h"

template<class K>
class set
{
	class KeyOfValue
	{
	public:
		const K& operator()(const K& key)
		{
			return key;
		}
	};

public:
	typedef typename RBTree<K, K, KeyOfValue>::_iterator iterator;

	iterator begin()
	{
		return tree.begin();
	}
	iterator end()
	{
		return tree.end();
	}
	bool empty() const
	{
		return tree.empty();
	}
	pair<iterator, bool> insert(const K& key)
	{
		return tree.insert(key);
	}
private:
	RBTree<K, K, KeyOfValue> tree;
};
void testset()
{
	set<int> s;
	s.insert(3);
	s.insert(6);
	s.insert(3);
	s.insert(1); 
	s.insert(4); 
	s.insert(7);
	s.insert(2);

	set<int>::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值