【c++学习】set与map的初步模拟封装

本文介绍了如何将红黑树泛型化以适应不同类型的值,包括节点的更改、插入操作中使用仿函数进行值比较,以及set和map的迭代器设计。通过模板和特定的比较函数,作者展示了如何处理set和map中键值对的不同需求。
摘要由CSDN通过智能技术生成

1、泛型红黑树

1.1 set与map

set:
在这里插入图片描述

上图我们可以看到set底层使用的是红黑树,而他的value值存的却是Key的值,
map:
在这里插入图片描述
我们发现map的底层也是红黑树,而map的value的值却是pair<const K,T>类型的
对于不同的传值要求如果要造两棵红黑树的话是一种治标不治本的效果,所以我们要造出一个泛型红黑树,任何值都可以接受。
相较于上一章的红黑树我们就需要更改。

1.2 节点的更改

使用模板,这样传过来的值都可以接受。

template <class T>
struct RBTreeNode
{
	RBTreeNode<T>* _left;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _parent;
	Color _col;
	T _data;

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

1.3 插入的更改

对于插入唯一需要着重的点是set和map传值类型不同,那么相对于值比较也需要不同的方法,所以我们可以在这两个类里面做一个特定的仿函数,来提取想要比较的值。
仿函数提取set中的比较值:

struct SetKeyOfT
{
	const K& operator()(const K& key)
	{
		return key;
	}
};

仿函数提取map中的比较值:

		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};

插入的具体更改:
通过仿函数来提取具体的值来进行比较。

	if (key(cur->_data) < key(data))
	{
		parent = cur;
		cur = cur->_right;
	}
	else if (key(cur->_data) > key(data))
	{
		parent = cur;
		cur = cur->_left;
	}
	else
	{
		return false;
	}
}

2、set与map的迭代器

由于我么这两个类用的是同一个红黑树,所以我们可以把迭代器具体实现放在红黑树中方便使用。
构建一个迭代器结构体:

struct RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T> Self;

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

运算符*

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

运算符->

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

运算符++

1、因为红黑树的中序是有序的,所以++是找到该节点在中序中的下一个节点
2、因为中序是左中右,所以我们可以分为右子树存在和不存在来讨论下一个节点是谁
3、当右子树存在时,右子树的最左节点即是下一个节点
4、当右子树不存在时,我们需要向上寻找,因为中序是左中右的,所以该子树已经被遍历完了,则++操作后应该在该结点的祖先结点中找到孩子不在父亲右的祖先

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

		return *this;
	}

运算符–

基本与++相似。

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

运算符!=

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

运算符==

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

begin()与end()

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

	return iterator(subLeft);
}

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

set与map的类封装

set:

#pragma once
#include "RBTree.h"
namespace zyf
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, const K, SetKeyOfT>::iterator iterator;

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

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

		bool insert(const K& key)
		{
			return _t.insert(key);
		}
	private:
		RBTree<K, const K, SetKeyOfT> _s;
	};

}

map:

#pragma once
#include "RBTree.h"
namespace zyf
{
	template<class K , class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;

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

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

		bool insert(const pair<K, V>& kv)
		{
			return _t.Insert(kv);
		}
		bool insert(const pair<K, V>& kv)
		{
			return _m.insert(kv);
		}
	private:
		RBTree < K, pair<K, V>,MapKeyOfT> _m;
	};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值