C++进阶:map与set简单自实现

1. map与set封装红黑树的方式

1.1 大概实现思路

  1. STL库中,实现的map与set其底层都为红黑树这种数据结构,在前面的学习中,我们已经简单模拟实现了红黑树。
  2. 因此,对于map与set的实现无需再去从零开始一一构建,而是可以采用类似于栈与队列这两个容器适配器的形式,直接将红黑树进行封装,调用其的各种方法接口间接实现。

1.2 红黑树模板抽象

  1. 虽然map与set的底层数据结构都为红黑树,但是,它们也并不是完全相同,map中存储的数据结点为KV类型,而set中存储的数据结点为K类型,所以,两者在接口与使用上也有所不同。
  2. 可仅仅因此不大的差别就再写一份高度类同的红黑树代码,就不免冗余性过高,由此,我们仿照库中实现的类似方式,将红黑树抽象为模板,通过模板参数来调整细节的方式,来同时适配map与set的需求。
//红黑树模板参数
template<class K, class T, class KeyOfT>
//参数K:set与map的key值类型,K参数的存在是必要的,否则无法进行此类型函数参数的声明
//参数T:set中也为key值类型,而map中为pair<K, V>类型
//参数KeyOfT:仿函数类型,从T类型结点中提取出key值,进行查找,插入等操作必须获知与比对key值

1.3 红黑树的迭代器

  1. 当调用库中的map与set容器时,我们使用相应迭代器遍历其中存储数据,得到的是一串排序好的有序数据。
  2. 因为map与set的底层本质上为一棵搜索二叉树,这种遍历后得到的数据特点,我们不难知道,迭代器底层实则是在由整颗树最左侧结点做中序遍历,那么,其底层的逻辑究竟应该怎么去实现呢?

2. 红黑树模板的实现

2.1 结点结构的定义

//结点结构
enum colour
{
	Red,
	Black
};

template<class K, class T>
struct RBTreeNode
{
	RBTreeNode<K, T>* _left;
	RBTreeNode<K, T>* _right;
	RBTreeNode<K, T>* _parent;
	T _kv;
	colour _col;

	RBTreeNode(const T& kv)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_kv(kv)
		,_col(Red)
	{}
};

2.2 红黑树迭代器的实现

2.2.1 迭代器的结构

//定义一个迭代器模板,适配出普通迭代器与const迭代器
template<class K, class T, class Ref, class Ptr>
class RBTree_iterator
{
	typedef RBTreeNode<K, T> RBTNode;
public:
	//构造
	RBTree_iterator(RBTNode* node)
		:_node(node)
	{}
	
	//拷贝构造
	RBTree_iterator(const RBTree_iterator& it)
	{
		_node = it._node;
	}

	//后置++,左根右
	RBTree_iterator operator++(int);
	
	//后置--,右根左
	RBTree_iterator operator--(int);

	//const T&
	Ref operator*();

	//const T*
	Ptr operator->();

	//指向结点相同
	bool operator==(RBTree_iterator it);

	bool operator!=(RBTree_iterator it);

private:
	RBTNode* _node;
};

2.2.2 迭代器的方法实现

  1. 杂项
//const T&
Ref operator*()
{
	return _node->_kv;
}

//const T*
Ptr operator->()
{
	return &_node->_kv;
}

//指向结点相同
bool operator==(RBTree_iterator it)
{
	return _node == it._node;
}

bool operator!=(RBTree_iterator it)
{
	return _node != it._node;
}
  1. 后置++与–
    在这里插入图片描述
//先使用,再++
//operator++,左根右
RBTree_iterator operator++(int)
{
	RBTree_iterator cp(*this);

	//左根右
	if (_node->_right)
	{
		//向左找
		RBTNode* SubLeft = _node->_right;
		while (SubLeft->_left)
		{
			SubLeft = SubLeft->_left;
		}

		_node = SubLeft;
	}
	else
	{
		RBTNode* cur = _node;
		RBTNode* parent = cur->_parent;
		if (cur == parent->_left)
		{
			_node = parent;
		}
		else
		{
			//一层一层向上找,空结点检测
			while (parent && cur == parent->_right)
			{
				cur = parent;
				parent = cur->_parent;
			}

			_node = parent;
		}
	}

	return cp;
}

//operator--,右根左
RBTreeNode_iterator operator--(int)
{
	RBTree_iterator cp(*this);

	//右根左
	if (_node->_left)
	{
		//向右找
		RBTNode* SubRight = _node->_left;
		while (SubRight->_right)
		{
			SubRight = SubRight->_right;
		}

		_node = SubRight;
	}
	else
	{
		RBTNode* cur = _node;
		RBTNode* parent = _node->_parent;
		while (parent && cur == parent->_left)
		{
			cur = parent;
			parent = cur->_parent;
		}

		_node = parent;//处理逻辑同时符合两种情况
	}

	return cp;
}

2.3 树结构的定义

//树结构
template<class K, class T, class KeyOfT>
class RBTree
{
	typedef RBTreeNode<K, T> RBTNode;
public:
	//查找
	bool Find(const K& key);

	//插入
	pair<iterator, bool> Insert(const T& kv);
	
private:
	RBTNode* _root = nullptr;
	KeyOfT con;
}

2.4 红黑树接口实现

2.4.1 插入

//插入
pair<iterator, bool> Insert(const T& kv)
{
	//找到插入位置
	RBTNode* cur = _root;
	RBTNode* parent = nullptr;
	while (cur)
	{
		if (con(kv) < con(cur->_kv))
		{
			parent = cur;
			cur = cur->_left;
		}
		else if (con(kv) > con(cur->_kv))
		{
			parent = cur;
			cur = cur->_right;
		}
		else
		{
			//有相同值,插入失败
			//return false;
			return make_pair(iterator(cur), false);
		}
	}

	//插入
	RBTNode* newnode = new RBTNode(kv);
	cur = newnode;
	if (_root == nullptr)//根结点
	{
		_root = cur;
		_root->_col = Black;
		//return true;
		return make_pair(iterator(cur), true);
	}
	else
	{
		if (con(kv) < con(parent->_kv))
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
	}

	//判断与调整
	while (parent)
	{
		//父亲结点为黑色
		if (parent->_col == Black)
		{
			break;
		}
		else//父结点为红色
		{
			RBTNode* grandparent = parent->_parent;
			RBTNode* uncle = grandparent->_left;
			if (parent == grandparent->_left)
			{
				uncle = grandparent->_right;
			}

			//叔叔结点存在且为红色
			if (uncle && uncle->_col == Red)
			{
				parent->_col = uncle->_col = Black;
				grandparent->_col = Red;
				cur = grandparent;
				//注,父节点存放变量也需重置
				parent = cur->_parent;
			}
			else//叔叔结点为黑色/不存在
			{
				if (parent == grandparent->_left)//左外高
				{
					if (cur == parent->_left)//右单旋
					{
						//      g
						//   p      u
						//c
						RotateR(grandparent);
						parent->_col = Black;
						grandparent->_col = Red;
					}
					else//左右双旋
					{
						//      g
						//   p      u
						//     c
						RotateLR(grandparent);
						cur->_col = Black;
						grandparent->_col = Red;
					}
				}
				else//右外高
				{
					if (cur == parent->_right)//左单旋
					{
						//   g
						//u      p
						//          c
						RotateL(grandparent);
						parent->_col = Black;
						grandparent->_col = Red;
					}
					else//右左双旋
					{
						//   g
						//u      p
						//     c
						RotateRL(grandparent);
						cur->_col = Black;
						grandparent->_col = Red;
					}
				}

				break;
			}
		}
	}

	_root->_col = Black;

	return make_pair(iterator(newnode), true);
}

2.4.2 查找

//查找
bool Find(K key)
{
	RBTNode* cur = _root;
	while (cur)
	{
		if (key < con(cur->_kv))
		{
			cur = cur->_left;
		}
		else if (key > con(cur->_kv))
		{
			cur = cur->_right;
		}
		else
		{
			return true;
		}
	}

	return false;
}

2.4.3 迭代器相关

typedef RBTree_iterator<K, T, T&, T*> iterator;
typedef RBTree_iterator<K, T, const T&, const T*> const_iterator;

iterator begin()
{
	RBTNode* cur = _root;
	while (cur->_left)
	{
		cur = cur->_left;
	}

	return cur;
}

iterator end()
{
	return nullptr;
}

const iterator cbegin() const
{
	RBTNode* cur = _root;
	while (cur->_left)
	{
		cur = cur->_left;
	}

	return cur;
}

const iterator cend() const
{
	return nullptr;
}

3. map与set的自实现

3.1 set封装

template<class K>
class myset
{
	struct KeyOfT
	{
		K operator()(const K& key)
		{
			return key;
		}
	};

	typedef RBTree_iterator<K, K, K&, K*> iterator;
	typedef RBTree_iterator<K, K, const K&, const K*> const_iterator;
public:
	bool Find(K key)
	{
		return tree.Find(key);
	}

	pair<iterator, bool> Insert(K key)
	{
		return tree.Insert(key);
	}

	iterator begin()
	{
		return tree.begin();
	}

	iterator end()
	{
		return tree.end();
	}

	const_iterator cbegin() const
	{
		return tree.cbegin();
	}

	const_iterator cend() const
	{
		return tree.cend();
	}

	void InOrder()
	{
		tree.InOrder();
	}

private:
	RBTree<K, K, KeyOfT> tree;
};

3.2 map封装

template<class K, class V>
class mymap
{
	struct KeyOfT
	{
		K operator()(const pair<const K, V> kv)
		{
			return kv.first;
		}
	};
	typedef RBTree_iterator<K, pair<const K, V>, pair<const K, V>&, pair<const K, V>*> iterator;
	typedef RBTree_iterator<K, pair<const K, V>, const pair<const K, V>&, const pair<const K, V>*> const_iterator;
public:
	bool Find(K key)
	{
		return tree.Find(key);
	}

	pair<iterator, bool> Insert(const pair<K, V> kv)
	{
		return tree.Insert(kv);
	}

	//迭代器
	iterator begin()
	{
		return tree.begin();
	}

	iterator end()
	{
		return tree.end();
	}

	const_iterator cbegin() const
	{
		return tree.cbegin();
	}

	const_iterator cend() const
	{
		return tree.cend();
	}

	V& operator[](const K key)
	{
		pair<iterator, bool> ret = Insert(make_pair(key, V()));

		return ret.first->second;
	}

private:
	RBTree<K, pair<const K, V>, KeyOfT> tree;
};
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值