红黑树来实现map&set

Posted 小羊教你来编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了红黑树来实现map&set相关的知识,希望对你有一定的参考价值。

在这里插入图片描述

目录:

一.修改红黑树

这篇博客是对于红黑树来实现map和set,所以代码不详细的注释,了解红黑树看红黑树的具体实现

底层实现原理:

如果我们要利用红黑树来实现map和set的时候,我们就会发现map是对应的<K,V>键值对,而set是<K,K> 所以我们在这里进行实现的时候,就要引入第三个模板类,首先对于要输出的值进行一个封装,再通过其第三个模板类进行数据的引入,直接去引入对饮的个kv键值对或者直接引入对应得val即可.

enum COLOR{};
template <class V>
struct RBNode{};
//KeyOfValue: 通过v获取对应的K
template<class K, class V, class KeyOfValue>
class RBTree{
public:
	typedef RBNode<V> Node;	
	
	RBTree()
		:_header(new Node)
	{
	
		_header->_left = _header->_right = _header;
	}

	bool insert(const V& val){


		if (_header->_parent == nullptr){

		
			Node* root = new Node(val);

			_header->_parent = root;
			root->_parent = _header;
			_header->_left = _header->_right = root;

	
			root->_color = BLACK;
			return true;
		}

		Node* cur = _header->_parent;
		Node* parent = nullptr;

		KeyOfValue kov;
		while (cur){

			parent = cur;

//if (cur->_val.first ==val.first)
			if (kov(cur->_val) == kov(val))	//在这里判断的时候,引入第三个模板来实现取出对应的数据
			{
				return false;
			}
//else if (cur->_val.first > val.first)
			else if (kov(cur->_val)>kov(val))
			{
				cur = cur->_left;
			}
			else{
				cur = cur->_right;
			}
		}
	
		cur = new Node(val);
		if (kov(parent->_val) > kov(cur->_val))
			parent->_left = cur;
		else
			parent->_right = cur;
		cur->_parent = parent;
		
		while (cur != _header->_parent && cur->_parent->_color == RED){

			parent = cur->_parent;
			Node* gfather = parent->_parent;

			if (gfather->_left == parent){

				Node* uncle = gfather->_right;
		
				if (uncle&&uncle->_color == RED){

					parent->_color = uncle->_color = BLACK;
					gfather->_color = RED;
	
					cur = gfather;
				}
				else{

					if (cur == parent->_right){

						RotateL(parent);
						swap(cur, parent);
					}
		
					RotateR(gfather);
					parent->_color = BLACK;
					gfather->_color = RED;
					break;
				}
			}
			else{
//gfather->right=parent
				Node* uncle = gfather->_left;
				if (uncle&&uncle->_color == RED){

					parent->_color = uncle->_color = BLACK;
					gfather->_color = RED;
					cur = gfather;
				}
				else{

					if (cur == parent->_left){

						RotateR(parent);
						swap(cur, parent);
					}
					RotateL(gfather);

					parent->_color = BLACK;
					gfather->_color = RED;
					break;
				}
			}
		}
		_header->_parent->_color = BLACK;

		_header->_left = leftMost();
		_header->_right = rightMost();
	}
	//下面这些没有写的接口和原来的代码一致,没有改变,想看去看红黑树的代码
	void RotateL(Node* parent);
	void RotateR(Node* parent);
	Node* leftMost();
	Node* rightMost();
	void inorder();
	void _inorder(Node* root);
	bool isBalance();
	bool _isBalance(Node* root, int& bCount, int curBCount);

private:
	Node* _header;
};

二.红黑树实现map

template<class K, class T>
class Map{
	//通过这里的传值来体现map和set的不同
	struct MapKeyOfValue{
		const K& operator()(const pair<K, T>& val){		//构建出对应的值

			return val.first;
		}
	};

public:

	bool insert(const pair<K, T>& kv){	//插入接口直接调用红黑树的接口

		return _rbt.insert(kv);
	}

	T& operator[](const K& key){

		bool ret = _rbt.insert(make_pair(key, T()));	//调用红黑树的接口将对应的两个值插入
	}

private:
	typedef RBTree<K, pair<K, T>, MapKeyOfValue> rbt;	//引入第三个模板类
	rbt _rbt;
};

三.红黑树实现set

template<class K>
class Set{

	struct SetKeyOfValue{
		const K& operator()(const K& val){	//构造函数,只传入对应的key

			return val;
		}
	};
public:
	bool insert(const K& val){		//只传入对应的key

		return _rbt.insert(val);	
	}
private:
	typedef RBTree<K, K, SetKeyOfValue> rbt;	//引入第三个对应的模板
	rbt _rbt;
};

注意:

我们在这里主要理解的是,在我们引入第三个模板的时候,就可以不需要在红黑树上进行改变就可以同时的实现map和set,我们可以直接在对应的构造函数的私有类里面去定义取出对应的需要红黑树的哪一部分的数据.

以上是关于红黑树来实现map&set的主要内容,如果未能解决你的问题,请参考以下文章

map和set的模拟实现

STL详解—— 用一棵红黑树同时封装出map和set

使用红黑树封装map和set

使用红黑树封装map和set

[C/C++]详解STL容器9-基于红黑树模拟实现map和set

[C/C++]详解STL容器9-基于红黑树模拟实现map和set