【C++】STL之map、set类源码剖析

目录

概述

算法

源码

Iterator.h

RBTree.h

Map.h

Set.h

test.cpp


概述

map和set都是STL中的关联式容器,而vector、list、deque是序列式容器。

map是映像,set是集合,map元素的数据类型是std::pair格式(key/value形成映像),set元素的数据类型只有key值。

map和set的实现是对红黑树的封装,map根据key值进行排序,map和set的key值都是不可修改的,但是map的value值可以修改。

map和set支持迭代器、反向迭代器、常量迭代器,并且通过精妙的泛型设计,大大简化了代码,但是完成两个STL容器的基本功能封装,依旧需要千行代码左右。

算法

本文里面的红黑树模块相较于上一篇博客,做了部分修改,设计了红黑树的迭代器,并将迭代器单独作为一个模块,通过普通迭代器构造出反向迭代器,这里采用的设计思路与之前 list 容器的迭代器设计思路是相同的。

红黑树在普通迭代器类中,设计出通过普通迭代器拷贝出const迭代器,这样解决了set模块的insert函数的返回值由红黑树的iterator转换为const_iterator问题。

红黑树迭代器的自增、自减都有其独特的算法,但是本文中的红黑树结构,与stl标准库中的红黑树略有不同,本文的红黑树没有一个空的头结点,即:当迭代器迭代到end(),即迭代器指向nullptr。而在stl标准库中,迭代器走到end()时,迭代器指向空的头结点。

红黑树的构造可以通过元素插入构造或者拷贝构造,拷贝构造设计了迭代器构造,这也是拷贝构造的核心。map和set的迭代器构造、拷贝构造、赋值构造本质都是调用红黑树的迭代器构造。

红黑树的泛型设计十分精妙(红黑树自身并不知道自己是要构造出一个map还是set,但是他必须兼容这两种容器的所有特性),并通过仿函数KofT设计,实现了从传入的元素数据(key值或key/value键值对)之中提取到key值进行排序

set模块的迭代器设计十分精妙,因为set里面元素都是key值,而红黑树的key值是不允许修改的,所以无论是set的普通迭代器iterator还是const_iterator,其本质都是const_iterator,所以set在设计时用const_iterator来重命名iterator,在普通迭代器的构造函数时加上了const修饰,而省略了const_iterator的构造函数,使iterator的构造函数能够对const_iterator构成重载。

map的 "[ ]" 运算符有特殊功能,即可以通过 "[ ] " 来进行数据插入、查找、统计,原理是:若 "[ ]" 里面数据的key值已经存在的话,则插入失败,insert函数返回已有节点的迭代器和一个bool值false,然后 "[ ] " 运算符返回这个迭代器(pair)的第二个数据(value);若 "[ ]"  里面数据的key不存在,则插入成功,insert函数返回新插入节点的迭代器和bool值true,然后 "[ ]" 运算符返回这个键值对迭代器的value值。因此我们可以通过这个原理对键值对的第二个数据为整型类型的数据进行计数操作。

源码

Iterator.h

#pragma once

enum Colour
{
	RED,
	BLACK
};

template
struct RBTreeNode
{
	T _data;
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	Colour _col;

	RBTreeNode(const T data)
		: _data(data), _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED)
	{}
};

template
struct RBTreeIterator
{
	typedef RBTreeNode Node;
	typedef RBTreeIterator Self;
	typedef RBTreeIterator iterator;

	Node* _node;

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

	// 普通迭代器构造const迭代器
	RBTreeIterator(const iterator& it)
	{
		_node = it._node;
	}

	Ref operator*()
	{
		return _node->_data;
	}
	Ptr operator->()
	{
		return &_node->_data;
	}

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

		return *this;
	}
	Self operator++(int)
	{
		Self tmp(*this);
		++(*this);
		return tmp;
	}

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

		return *this;
	}
	Self operator--(int)
	{
		Self tmp(*this);
		--(*this);
		return tmp;
	}

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

template
struct RBTreeReverseIterator
{
	typedef RBTreeReverseIterator Self;

	Iterator _it;
	RBTreeReverseIterator(Iterator it)
		: _it(it)
	{}

	Ref operator*()
	{
		Iterator tmp = _it;
		return *tmp;
	}
	Ptr operator->()
	{
		return &(operator*());
	}

	Self& operator++()
	{
		--_it;
		return *this;
	}
	Self operator++(int)
	{
		Self tmp(*this);
		--_it;
		return tmp;
	}

	Self& operator--()
	{
		++_it;
		return *this;
	}
	Self operator--(int)
	{
		Self tmp(*this);
		++_it;
		return tmp;
	}

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

RBTree.h

#pragma once
#include "Iterator.h"

template
class RBTree
{
	// 私有
	typedef RBTreeNode Node;
public:
	typedef RBTreeIterator iterator;
	typedef RBTreeIterator const_iterator;
	typedef RBTreeReverseIterator reverse_iterator;
	typedef RBTreeReverseIterator const_reverse_iterator;

	iterator begin()
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}

		return iterator(left);
	}
	iterator end()
	{
		return iterator(nullptr);
	}

	const_iterator begin()const
	{
		Node* left = _root;
		while (left && left->_left)
		{
			left = left->_left;
		}

		return const_iterator(left);
	}
	const_iterator end()const
	{
		return const_iterator(nullptr);
	}

	reverse_iterator rbegin()
	{
		Node* right = _root;
		while (right && right->_right)
		{
			right = right->_right;
		}

		return reverse_iterator(iterator(right));
	}
	reverse_iterator rend()
	{
		return reverse_iterator(iterator(nullptr));
	}

	const_reverse_iterator rbegin()const
	{
		Node* right = _root;
		while (right && right->_right)
		{
			right = right->_right;
		}

		return const_reverse_iterator(const_iterator(right));
	}
	const_reverse_iterator rend()const
	{
		return const_reverse_iterator(const_iterator(nullptr));
	}

	// 迭代器构造
	template
	RBTree(Iterator first, Iterator last)
	{
		_root = nullptr;
		while (first != last)
		{
			insert(*first);
			++first;
		}
	}

	RBTree()
		: _root(nullptr)
	{}

	std::pair insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return std::make_pair(iterator(_root), true);
		}

		KofT kot;

		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (kot(cur->_data) < kot(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > kot(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return std::make_pair(iterator(cur), false);
			}
		}

		cur = new Node(data);
		Node* newNode = cur;
		cur->_col = RED;
		if (kot(parent->_data) < kot(data))
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		// 变色、旋转
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;

				if (uncle && uncle->_col == RED)
				{
					// 情况1:叔叔存在且为红
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{
						// 情况2: 右单旋
						rotate_right(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						// 情况3: 左右双旋
						rotate_left(parent);
						rotate_right(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}
			else
			{
				Node* uncle = grandfather->_left;

				if (uncle&& uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_right)
					{
						// 情况2: 左单旋
						rotate_left(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						// 情况3: 右左双旋
						rotate_right(parent);
						rotate_left(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}
					break;
				}
			}

		}

		_root->_col = BLACK;

		return std::make_pair(iterator(newNode), true);
	}

	void rotate_right(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}

		subL->_right = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subL;
		if (ppNode == nullptr)
		{
			subL->_parent = nullptr;
			_root = subL;
		}
		else
		{
			if (parent == ppNode->_left)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
			subL->_parent = ppNode;
		}
	}

	void rotate_left(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = parent;
		}

		subR->_left = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;
		if (ppNode == nullptr)
		{
			subR->_parent = nullptr;
			_root = subR;
		}
		else
		{
			if (parent == ppNode->_left)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
			subR->_parent = ppNode;
		}
	}

	void in_order()
	{
		_in_order(_root);
		std::cout << std::endl;
	}

	bool is_balance()
	{
		if (_root == nullptr)
		{
			return true;
		}

		if (_root->_col != BLACK)
		{
			return false;
		}

		int ref = 0;
		Node* left = _root;
		while (left)
		{
			if (left->_col == BLACK)
			{
				++ref;
			}
			left = left->_left;
		}

		return _is_balance(_root, 0, ref);
	}

private:
	void _in_order(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_in_order(root->_left);
		std::cout << root->_data << std::endl;
		_in_order(root->_right);
	}

	// 检查是否有联系的红节点
	bool _is_balance(Node* root, int blackNum, const int ref)
	{
		if (root == nullptr)
		{
			if (blackNum != ref)
			{
				std::cout << "路径黑色节点跟最左路径不相等" << std::endl;
				return false;
			}
			return true;
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			std::cout << "出现连续红节点: " << root->_data.first << ", " << root->_parent->_data.first << std::endl;
			return false;
		}

		if (root->_col == BLACK)
		{
			++blackNum;
		}

		return _is_balance(root->_left, blackNum, ref)
			&& _is_balance(root->_right, blackNum, ref);
	}

private:
	Node* _root = nullptr;
};

Map.h

#pragma once

#include "RBTree.h"

template
class Map
{
	struct MapKofT
	{
		const K& operator()(const std::pair& kv)
		{
			return kv.first;
		}
	};
public:
	typedef typename RBTree, MapKofT>::iterator iterator;
	typedef typename RBTree, MapKofT>::const_iterator const_iterator;
	typedef typename RBTree, MapKofT>::reverse_iterator reverse_iterator;
	typedef typename RBTree, MapKofT>::const_reverse_iterator const_reverse_iterator;

	iterator begin()
	{
		return _t.begin();
	}
	iterator end()
	{
		return _t.end();
	}

	const_iterator begin()const
	{
		return _t.begin();
	}
	const_iterator end()const
	{
		return _t.end();
	}

	reverse_iterator rbegin()
	{
		return _t.rbegin();
	}
	reverse_iterator rend()
	{
		return _t.rend();
	}

	const_reverse_iterator rbegin()const
	{
		return _t.rbegin();
	}
	const_reverse_iterator rend()const
	{
		return _t.rend();
	}

	template
	Map(Iterator first, Iterator last)
	{
		_t = RBTree, MapKofT>(first, last);
	}

	void swap(Map& m)
	{
		std::swap(_t, m._t);
	}

	Map()
		: _t(RBTree, MapKofT>())
	{}
	Map(const Map& m)
	{
		Map tmp(m._t.begin(), m._t.end());
		swap(tmp);
	}
	Map& operator=(const Map m)
	{
		swap(m);
		return *this;
	}

	std::pair insert(const std::pair& kv)
	{
		return _t.insert(kv);
	}

	V& operator[](const K& key)
	{
		std::pair ret = insert(std::make_pair(key, V()));
		return ret.first->second;
	}

private:
	RBTree, MapKofT> _t;
};

Set.h

#pragma once

#include "RBTree.h"

template
class Set
{
	struct SetKofT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
public:
	typedef typename RBTree::const_iterator iterator;
	typedef typename RBTree::const_iterator const_iterator;
	typedef typename RBTree::const_reverse_iterator reverse_iterator;
	typedef typename RBTree::const_reverse_iterator const_reverse_iterator;

	iterator begin()const
	{
		return _t.begin();
	}
	iterator end()const
	{
		return _t.end();
	}

	reverse_iterator rbegin()const
	{
		return _t.rbegin();
	}
	reverse_iterator rend()const
	{
		return _t.rend();
	}

	template
	Set(Iterator first, Iterator last)
	{
		_t = RBTree(first, last);
	}

	void swap(Set& s)
	{
		std::swap(_t, s._t);
	}

	Set()
		: _t(RBTree())
	{}
	Set(const Set& s)
	{
		Set tmp(s.begin(), s.end());
		swap(tmp);
	}
	Set& operator=(const Set s)
	{
		swap(s);
		return *this;
	}

	std::pair insert(const K& k)
	{
		std::pair::iterator, bool> ret = _t.insert(k);
		return std::pair(ret.first, ret.second);
	}

private:
	RBTree _t;
};

test.cpp

#include 
#include 
#include 
#include "Map.h"
#include "Set.h"

void test_map()
{
	int a[] = { 8, 4, 12, 2, 6, 10, 30, 14, 32, 28 };

	Map m;
	for (auto e : a)
	{
		m.insert(std::make_pair(e, e));
	}

	Map::iterator it = m.begin();
	while (it != m.end())
	{
		std::cout << (*it).first << ": " << (*it).second << std::endl;
		//++it;
		it++;
	}
	std::cout << std::endl;
	for (auto e : m)
	{
		std::cout << e.first << ": " << e.second << std::endl;
	}
	std::cout << std::endl;

	Map::reverse_iterator rit = m.rbegin();
	while (rit != m.rend())
	{
		std::cout << rit->first << ": " << rit->second << std::endl;
		rit++;
	}
	std::cout << std::endl;

	const Map m1(m.begin(), m.end());
	Map::const_iterator cit = m1.begin();
	while (cit != m1.end())
	{
		std::cout << cit->first << ": " << cit->second << std::endl;
		cit++;
	}
	std::cout << std::endl;

	const Map m2(m1);
	Map::const_reverse_iterator crit = m2.rbegin();
	while (crit != m2.rend())
	{
		std::cout << crit->first << ": " << crit->second << std::endl;
		++crit;
	}
	std::cout << std::endl;

	Map m3 = m2;
	for (auto& e : m3)
	{
		// map的key不可修改,value可改
		//e.first += 1;
		e.second /= 2;
		std::cout << e.first << ": " << e.second << std::endl;
	}
	std::cout << std::endl;

	std::vector food = {
		"蛋糕", "西瓜", "啤酒", "苹果", "香蕉", "蛋糕", "牛肉",
		"西瓜", "苹果", "啤酒", "西瓜", "牛肉", "蛋糕", "蛋糕",
		"西瓜", "西瓜", "牛肉", "苹果", "香蕉", "蛋糕", "西瓜"
	};
	Map foodMap;
	for (auto& e : food)
	{
		foodMap[e]++;
	}
	for (auto& e : foodMap)
	{
		std::cout << e.first << ": " << e.second << std::endl;
	}
	std::cout << std::endl;
}

void test_set()
{
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };

	Set s;
	for (auto e: a)
	{
		s.insert(e);
	}
	
	Set::iterator it = s.begin();
	while (it != s.end())
	{
		std::cout << *it << ' ';
		++it;
	}
	std::cout << std::endl;
	for (const auto& e : s)
	{
		std::cout << e << ' ';
	}
	std::cout << std::endl;

	Set::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		std::cout << *rit << ' ';
		++rit;
	}
	std::cout << std::endl;

	const Set s1(s.begin(), s.end());
	Set::const_iterator cit = s1.begin();
	while (cit != s1.end())
	{
		std::cout << *cit << ' ';
		++cit;
	}
	std::cout << std::endl;

	const Set s2(s1);
	Set::const_reverse_iterator crit = s2.rbegin();
	while (crit != s2.rend())
	{
		std::cout << *crit << ' ';
		++crit;
	}
	std::cout << std::endl;

	const Set s3 = s2;
	for (auto& e : s3)
	{	
		// set的值不可修改
		// e++;
		std::cout << e << ' ';
	}
	std::cout << std::endl;
}

int main()
{
	test_map();
	test_set();
	
	return 0;
}

你可能感兴趣的:(c++,STL,map,set,红黑树)