C++|set、map模拟实现<——红黑树

目录

一、红黑树的迭代器

1.1红黑树迭代器框架

1.2operator*() && operator->()

1.3operator++()

1.4operator--()

1.5operator==()  && operator!=() 

1.6begin() && end()

二、如何用红黑树搭配map和set(仿函数)

 三、红黑树封装map和set(简易版)

3.1红黑树的构造(RBTree.h) 

3.2map的模拟实现(MyMap.h)

3.3set的模拟实现(MySet.h)

3.4测试(test.cpp)


 一、红黑树的迭代器

前一篇章,有了红黑树的了解,但那只实现了红黑树的插入部分,那么现在要用红黑树封装set、map容器,那有一个功能,就必须得实现,即迭代器,对于红黑树的迭代器该如何实现呢?参考前面篇章,list容器的迭代器的实现,同样的,红黑树将迭代器要实现的功能封装成了一个类,那么接下来进行一步步实现。

1.1红黑树迭代器框架

由于迭代器的遍历,实际就是遍历节点,在实现具体步骤之前,先带上节点,再把迭代器的框架搭好。 

	enum Color//对于红黑节点,用枚举结构来表示
	{
		RED,
		BLACK
	};



	template<class T>
	struct RBTreeNode
	{
		RBTreeNode(const T& data, Color color = RED)
			:_left(nullptr)
			,_right(nullptr)
			,_parent(nullptr)
			,_data(data)
			,_color(color)
		{}

		RBTreeNode<T>* _left;
		RBTreeNode<T>* _right;
		RBTreeNode<T>* _parent;

		T _data;

		Color _color;//默认给红色才符合规则,若默认给黑色的话,则插入的每个节点都是黑色节点,
		//那么就不能保证每条路径的黑色节点相同,违反了第4条性质。而给红色,就可以根据规则调整。
	};


	template<class T, class Ref, class Ptr>
	struct RBTreeIterator
	{

		typedef RBTreeNode<T> Node;
		typedef Node* PNode;
		typedef RBTreeIterator<T, Ref, Ptr> Self;
		PNode _node;

        RBTreeIterator(const PNode node)
			:_node(node)
		{}


         //.....


	};

1.2operator*() && operator->()

        T& operator*()
		{
			return _node->_data;//访问节点数据
		}
		T* operator->()
		{
			return &(operator*());//operator*() == _node->_data
		}

1.3operator++()

 对红黑树的遍历是一个中序遍历,遍历完后,得到的是一个有序序列。每++一次,跳到的位置是中序序列中的下一个位置。我们知道中序的访问顺序是,左根右,那么如何在树上进行操作而达到中序遍历呢?

大致可以分为两步:

1.当左子树与根访问完,要符合中序,得去右子树进行访问,同理右子树得满足中序遍历,首先就得找到右子树的最小节点,即最左节点。

抽象示意图:

2.当左子树未访问完,++时,就指向父节点,

抽象示意图:

或者当右子树访问完了,则说明一颗节点的整个左子树访问完了。那么++就是要找到这个节点

抽象示意图: 

        Self& operator++()
		{
			if (_node->_right)//左子树访问完,去访问右子树
			{
				_node = _node->_right;
				while (_node && _node->_left)
				{
					_node = _node->_left;
				}
			}
			else//左子树未访问完,或者右子树访问完
			{
				PNode cur = _node;
				PNode parent = cur->_parent;

				while (parent && cur != parent->_left)
				{
					cur = parent;
					parent = parent->_parent;
				}
				_node = parent;
			}

			return *this;
		}

1.4operator--()

那么,对于--操作,它与++操作是反过来的,是从大到小的一个遍历。

1. 当右子树与根访问完,要符合大到小的遍历,得去左子树进行访问,同理左子树得满足大到小的遍历,首先就得找到左子树的最大节点,即最右节点。

2.当右子树未访问完,或者左子树已访问完

Self& operator--()
		{
			PNode cur = _node;
			PNode parent = cur->_parent;
			if (_node->_left)//右子树访问完,去左子树访问
			{
				_node = _node->_left;
				while (_node->_right)
				{
					_node = _node->_right;
				}
			}
			else//右子树未访问完,或者左子树访问完
			{
				PNode cur = _node;
				PNode parent = cur->_parent;
				if (parent && cur != parent->_right)
				{
					cur = parent;
					parent = parent->_parent;
				}
				_node = parent;
			}
			return *this;
		}

1.5operator==()  && operator!=() 

        bool operator==(const Self& x) const
		{
			return _node ==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值