RBTree改造,并模拟实现set&map

文章详细介绍了如何为红黑树添加前置++和前置--操作,以便实现迭代器的向前和向后移动,同时讲解了在红黑树基础上模拟实现set和map的数据结构,包括数据存储位置的改造、插入和查找方法的调整以及仿函数的使用。
摘要由CSDN通过智能技术生成

目录

RBTree改造

给红黑树增加迭代器

前置++

前置--

RBT细节改造

模拟set

模拟map


RBTree改造

给红黑树增加迭代器

前置++

前置++的作用是找下一个较大的节点。

假如我们it指向的是5,++it则是将it指向6。加入it指向的是7,则++it则是将it指向8。

也就是说如果右子树不为空,++it是指向的是右子树的最左节点(较大的)。

如果右子树为空(说明该子树已被访问完),++it应该沿着根路径指向孩子是父亲左孩子的那个祖先

//前置++
	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;
	}

前置--

前置--的作用是找下一个较小的节点。

 假如it指向的是8,--it则是将it指向7。假如it指向的是12,--it则就将it指向了11。

也就是说如果左子树不为空,--it是指向的是左子树的最右节点(较小的)。

如果左子树为空(说明该子树已被访问完),--it应该沿着根路径指向孩子是父亲右孩子的那个祖先。++it的顺序是左根右,--it的顺序是右根左。

//前置--
	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 = parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

RBT细节改造

1、将节点存放数据的位置改为_data,也就是说无论是set还是map存放的数据都在这个_data里面。

template<class T>
struct rbtreeNode{
	rbtreeNode<T>* _left;
	rbtreeNode<T>* _right;
	rbtreeNode<T>* _parent;
	T _data;
	Color _col;
	rbtreeNode(const T& data)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_col(RED)
		,_data(data)
	{}
};

2、采用上边的方式的话,需要在RBTree中的函数模板中增加一个KeyOfT的仿函数,用于取set中的值,和map中的key进行比较。

3、迭代器的begin的位置应该找到最左节点(最小)

iterator begin() {
		Node* min = _pHead;
		while (min && min->_left) {
			min = min->_left;
		}
		return iterator(min);
	}

4、插入的返回值修改为pair<iterator,bool>类型,方便后边map的operator[]的实现

5、查找的返回值原本是Node*,而迭代器也相当于指针,所以也将放回置修改为迭代器

模拟set

set的底层就是红黑树,因此set的私有成员的类型就是红黑树。

RBTree<K, K, SetKeyOfT> _rt;

set里边需要写一个仿函数,让红黑树能拿到存储的数据。并将这个仿函数类型传给红黑树

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

其他的接口复用红黑树的就行了。完整的代码如下:

#pragma once
#include "RBTree1.h"
template<class K>
class mySet {
public:
	struct SetKeyOfT {
		const K& operator()(const K& k) {
			return k;
		}
	};
	typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
	iterator begin() {
		return _rt.begin();
	}
	iterator end() {
		return _rt.end();
	}
	pair<iterator,bool> insert(const K& key) {
		return _rt.Insert(key);
	}
	iterator find(const K& key) {
		return _rt.Find();
	}
	size_t size() {
		return _rt.Size();
	}
private:
	RBTree<K, K, SetKeyOfT> _rt;
};
void test_MySet() {
	mySet<int> ms;
	int a[] = { 7,4,1,8,5,2,9,6,3 };
	for (auto e : a) {
		ms.insert(e);
	}
	mySet<int>::iterator it = ms.begin();
	while (it != ms.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;
	cout << "size:" << ms.size() << endl;
}

模拟map

map的模拟和set类似,底层也是红黑树。我们这里说说map的operator[]的逻辑。insert的返回值是pair<iterator, bool>类型,insert插入原来没有的数据时,返回的是新插入节点的迭代器,并返回true。如果插入原本有的数据的时候,返回的是这个存在的key的迭代器,bool值为false而operator[]就是依赖这个insert来实现的。operator[]的返回值是value的引用,也就是说我们可以通过operator[]对value进行查找、修改和插入等操作。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值