19.C++ map/set--红黑树的实现

红黑树前言: 单从红黑树的基本实现来说,是比AVLTree的实现更简单,但要用一棵红黑树(一份红黑树代码)来实现map/set及其相应的迭代器是有难度的

目录

  • 红黑树的概念

  • 红黑树的性质

  • 红黑树的节点定义

  • 红黑树的实现

    • 红黑树的插入
      • 第一步的过程
      • 第二步的过程
    • 红黑树的旋转
    • 二叉树的查找
  • 红黑树的迭代器

  • map/set封装实现

  • 完整版参考代码

红黑树的概念

红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

红黑树的性质

  1. 每个结点不是红色就是黑色
  2. 根节点是黑色的
  3. 如果一个节点是红色的,则它的两个孩子结点是黑色的
  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点
  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

在这里插入图片描述

红黑树的定义

在这里插入图片描述

红黑树的实现

因为红黑树为二叉搜索树,所以红黑树遵守二叉搜索树的规则

红黑树的插入

红黑树就是在二叉搜索树的基础上引入颜色,因此AVL树也可以看成是二叉搜索树。那么
红黑树的插入过程可以分为两步:

  1. 按照二叉搜索树的方式插入新节点
  2. 调整节点颜色(旋转+变色)

第一步的过程:

按照二叉搜索树的方式插入新节点
在这里插入图片描述
请添加图片描述

第二步的过程:

调整结点颜色

红黑树的旋转

红黑树单旋的抽象图

情况一(只需要处理颜色):
p(parent)和u(uncle)都为红-------------------------------->调整:parent和uncle都变为黑,grandparent变为红(若grandparent为根,则将grandparent再变为黑)
情况一处理完后需要再往上处理(grandparent及其父亲若都为红的话)
在这里插入图片描述

情况二(需要旋转+处理颜色):
在这里插入图片描述

红黑树旋转演示:

红黑树的单旋(左单旋+右单旋+变色)
请添加图片描述
左单旋,右单旋参考代码:

void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		Node* ppNode = parent->_parent;
		parent->_right = subRL;
		parent->_parent = subR;
		subR->_left = parent;
		subR->_parent = ppNode;

		if (subRL)
		{
			subRL->_parent = parent;
		}
		if (_root == parent)
		{
			_root = subR;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
		}
	}
	void RotateR(Node* parent)
	{

		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		Node* ppNode = parent->_parent;


		if (subLR)
			subLR->_parent = parent;
		parent->_left = subLR;
		parent->_parent = subL;

		subL->_right = parent;
		subL->_parent = ppNode;

		if (_root == parent)
		{
			_root = subL;
		}
		else
		{
			if (ppNode->_left == parent)
				ppNode->_left = subL;
			else
				ppNode->_right = subL;
		}

	}

红黑树的双旋:

请添加图片描述
红黑树处理颜色:
在这里插入图片描述

二叉树的查找

查找和插入第一步的逻辑差不多
在这里插入图片描述

红黑树的迭代器

有了迭代器,之前的接口返回值都需变化一下。参考最后的完整代码
在这里插入图片描述
在这里插入图片描述

map/set的封装实现

在这里插入图片描述

完整版参考代码

#include<iostream>
#include<string>

using namespace std;

enum Colour
{
	BLACK,
	RED,
};


template<class T>
struct RBTreeNode
{
	RBTreeNode(const T& data)
		:_data(data)
	{}

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

	T _data;

	Colour _col = RED;

};



template<class T, class Ref, class Ptr>
struct __TreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef __TreeIterator<T, Ref, Ptr> Self;
	Node* _node;

	__TreeIterator(Node* node)
		:_node(node)
	{}

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

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

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

	Self operator--()
	{
		//与++是反逻辑
		return *this;
	}

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




template<class K, class T, class KeyOfT>
class RBTree
{
	typedef RBTreeNode<T> Node;
public:
	typedef __TreeIterator<T, T*, T&> iterator;
	typedef __TreeIterator<T, const T*, const T&> const_iterator;

	iterator begin()
	{
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			parent = cur;
			cur = cur->_left;
		}
		return iterator(parent);
	}

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

	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		Node* ppNode = parent->_parent;
		parent->_right = subRL;
		parent->_parent = subR;
		subR->_left = parent;
		subR->_parent = ppNode;

		if (subRL)
		{
			subRL->_parent = parent;
		}
		if (_root == parent)
		{
			_root = subR;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
		}
	}
	void RotateR(Node* parent)
	{

		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		Node* ppNode = parent->_parent;


		if (subLR)
			subLR->_parent = parent;
		parent->_left = subLR;
		parent->_parent = subL;

		subL->_right = parent;
		subL->_parent = ppNode;

		if (_root == parent)
		{
			_root = subL;
		}
		else
		{
			if (ppNode->_left == parent)
				ppNode->_left = subL;
			else
				ppNode->_right = subL;
		}

	}



	pair<iterator, bool> Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}

		Node* cur = _root;
		Node* parent = nullptr;

		KeyOfT koft;


		while (cur)
		{
			if (koft(cur->_data) > koft(data))
			{
				parent = cur;
				cur = cur->_left;
			}

			else if (koft(cur->_data) < koft(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}

		cur = new Node(data);

		if (koft(parent->_data) < koft(cur->_data))
		{
			cur->_parent = parent;
			parent->_right = cur;
		}
		else
		{
			cur->_parent = parent;
			parent->_left = cur;
		}

		if (parent->_col == BLACK)
		{
			return  make_pair(iterator(cur), true);
		}

		Node* ret = cur;
		while (parent && parent->_col == RED)
		{
			Node* grandparent = parent->_parent;
			if (grandparent->_left == parent)
			{
				//情况一
				Node* uncle = grandparent->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandparent->_col = RED;

					cur = grandparent;
					parent = grandparent->_parent;
				}

				else
				{
					if (parent->_right == cur)
					{
						RotateL(parent);
						swap(parent, cur);
					}
					RotateR(grandparent);
					grandparent->_col = RED;
					parent->_col = BLACK;
					break;
				}

			}
			else
			{
				Node* uncle = grandparent->_left;
				if (uncle && uncle->_col == RED)
				{
					uncle->_col = parent->_col = BLACK;
					grandparent->_col = RED;

					cur = grandparent;
					parent = cur->_parent;
				}
				else
				{
					if (parent->_left == cur)
					{
						RotateR(parent);
						swap(parent, cur);
					}
					RotateL(grandparent);
					grandparent->_col = RED;
					parent->_col = BLACK;

					break;
				}
			}
			_root->_col = BLACK;


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

	}


	iterator Find(T& data)
	{
		Node* cur = _root;
		if (KeyOfT(data) > KeyOfT(cur->_data))
		{
			cur = cur->_right;
		}
		else if (KeyOfT(data) < KeyOfT(cur->_data))
		{
			cur = cur->_left;
		}
		else
		{
			return iterator(cur);
		}
		return iterator(nullptr);

	}

private:
	Node* _root = nullptr;

};

template<class K, class V>
class map
{
public:
	struct MapKeyOfT
	{
		const K& operator()(const pair<K, V>& kv)
		{
			return kv.first;
		}
	};
	//typedef __TreeIterator<pair<K, V>> iterator;
	typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
	iterator begin()
	{
		return _rbt.begin();
	}

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

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

	V& operator[](const K& key)
	{
		pair<iterator, bool> ret = Insert(make_pair(key, V()));
		//return (*(ret.first)).second;
		return ret.first->second;
	}


private:
	RBTree<K, pair<K, V>, MapKeyOfT> _rbt;
};



template<class K>
class set
{
public:
	struct SetKeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
	//typedef __TreeIterator<K> iterator;
	typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;//调红黑树里的,红黑树又调了别人的
	iterator begin()
	{
		return _rbt.begin();
	}
	iterator end()
	{
		return _rbt.end();
	}

	pair<iterator, bool> Insert(const K& key)
	{
		return _rbt.Insert(key);
	}
private:
	RBTree<K, K, SetKeyOfT>_rbt;
};
void test()
{
	//map<int, int> m;
	//m.Insert(pair<int, int>(4, 4));
	//m.Insert(pair<int, int>(1, 1));
	//m.Insert(pair<int, int>(3, 3));
	//m.Insert(pair<int, int>(5, 5));
	//m.Insert(pair<int, int>(2, 2));

	//map<int, int>::iterator it = m.begin();

	//while (it != m.end())
	//{
	//	*(it) = make_pair(1, 1);
	//	cout << (*it).first << ":" << (*it).second << " ";
	//	++it;
	//}
	//cout << endl;
	//

	string strs[] = { "西瓜", "苹果", "香蕉", "苹果", "猕猴桃", "西瓜", "西瓜", "西瓜", "西瓜", };
	map<string, int> m;

	for (auto e : strs)
	{
		m[e]++;
	}
	for (auto e : m)
	{
		cout << e.first << ":" << e.second << " ";
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值