当前位置: 首页 > news >正文

C++模拟实现map和set

C++模拟实现map和set

  • 1、STL源代码分析
  • 2、实现出复用红黑树的框架
  • 3、实现红黑树的迭代器
  • 4、解决map和set中key不可修改问题
  • 5、解决insert返回值问题并实现operator[]
  • 完整代码

模拟实现map和set实际上是对红黑树的封装,如对红黑树的实现有疑问,请移步:C++手撕红黑树

1、STL源代码分析

map和set的底层都是红黑树,但是对于set来说,只存储key,而对于map来说,需要存储key和value——也就是pair类型。那么我们是实现两份红黑树的代码吗?实则不然,因为他们只有存储类型上的区别,所以我们要尽量的实现代码复用,通过对一份红黑树的代码封装同时实现map和set。
我们先来看看库里是怎么实现的:

在这里插入图片描述
我们可以看到,树的节点是继承了一个__rb_tree_node_base的类,这个基类存储了颜色、左孩子、右孩子、父亲的指针,继承后多了一个value_field的变量,这个变量实际上就是存储的数据类型。


继续往下看:
在这里插入图片描述
map的前两个模板参数:Key和T对应的就是key和value。将Key重命名为key_type,将pair<Key, T>重命名为value_type。然后将key_type和value_type作为模板参数传给红黑树。
set有一个Key模板参数,将Key重命名为key_type,还将Key重命名为value_type。然后将这两个作为模板参数传给红黑树。
红黑树的前两个模板参数为:Key和Value。红黑树内部将Value作为模板参数传给了红黑树的节点,红黑树的节点中通过Value声明了value_field成员变量,value_field就是存储的数据类型,所以红黑树是通过模板参数Value来控制存储的类型的。
我们分析发现,当使用的是map时,会将pair<K, V>传给红黑树的模板参数Value,红黑树存储的数据类型就是pair<K, V>。当使用的是set时,就会将Key传给红黑树的模板参数Value,这时候Key就是存储的数据类型。

接下来,我们开始封装实现map和set,请你思考一下:既然红黑树这里是通过模板参数Value来控制数据类型的,那么是不是就不需要传Key了?


2、实现出复用红黑树的框架

首先我们来修改红黑树的代码:我们将存储的数据类型统一定义为T。先修改节点的模板参数,然后修改红黑树的模板。注意:由于修改了模板参数名,因此类内涉及模板参数名的代码都需要修改。

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

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

template<class K, class T>
class RBTree
{
	typedef RBTreeNode<T> Node;
private:
	Node* _root = nullptr;
};

然后创建新文件:MySet.h和MyMap.h

#pragma once
#include "RBTree.h"

namespace zzy
{
	template<class K>
	class set
	{
	public:
	private:
		RBTree<K, K> _t;
	};
}
#pragma once
#include "RBTree.h"

namespace zzy
{
	template<class K, class V>
	class map
	{
	public:

	private:
		RBTree<K, pair<K, V>> _t;
	};
}

由于节点存储的数据类型我们改为_data,因此在红黑树中访问数据的代码都得修改。我们先来看Insert的修改:

bool Insert(const T& data)
{
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_col = BLACK;
		return true;
	}
	Node* parent = nullptr;
	Node* cur = _root;
	while (cur)
	{
		if (cur->_data < data)
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (cur->_data > data)
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			return false;
		}
	}
	cur = new Node(data);
	if (parent->_data < data)
		parent->_right = cur;
	else
		parent->_left = cur;
	cur->_parent = parent;

	while (parent && parent->_col == RED)
	{
		Node* grandfather = parent->_parent;
		if (grandfather->_left == parent)
		{
			Node* uncle = grandfather->_right;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;
				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
				if (parent->_left == cur)
				{
					RotateR(grandfather);
					grandfather->_col = RED;
					parent->_col = BLACK;
				}
				else
				{
					RotateL(parent);
					RotateR(grandfather);
					grandfather->_col = RED;
					cur->_col = BLACK;
				}
				break;
			}
		}
		else
		{
			Node* uncle = grandfather->_left;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;
				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
				if (parent->_right == cur)
				{
					RotateL(grandfather);
					grandfather->_col = RED;
					parent->_col = BLACK;
				}
				else
				{
					RotateR(parent);
					RotateL(grandfather);
					grandfather->_col = RED;
					cur->_col = BLACK;
				}
				break;
			}
		}
	}
	_root->_col = BLACK;
	return true;
}

在插入数据的过程中,需要将插入的数据data和当前节点的数据_data进行比较,如果是set就可以直接比,如果是map需要按key比。但是这里的比较有问题:当T为pair时,cur->_data和data就是两个pair的比较了,那么我们看看库里pair是否重载了比较,如果重载了是否满足我们的需求?
在这里插入图片描述
库里果然实现了pair类的六个运算符重载比较函数,那么是否满足我们的要求?——按key,也就是first来比较。
在这里插入图片描述
阅读代码:库里实现的operator<是先比较first是否小于,如果first不小于再比较second是否小于。也就是说如果first小于则返回true,如果frist不小于但是second小于也返回true,这种比较方式是不符合我们的需求的。因此我们要自己实现比较。
那么如何实现呢?——仿函数

在这里插入图片描述
我们发现红黑树的模板参数还存在KeyOfValue,这个名字很形象,就是取出Value中的Key。对于set,传入key直接将key返回。对于map,传入pair<key, value>,将key返回。
仿函数——可以像函数一样实现,实际上就是重载了operator()。所以我们需要在map和set中自己定义并将类传给红黑树,然后在红黑树中实例化对象,然后通过operator()取出T中的key,然后进行比较。
实现如下:这里我们直接定义为内部类更为方便

#pragma once
#include "RBTree.h"

namespace zzy
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:

	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
}
#pragma once
#include "RBTree.h"

namespace zzy
{
	template<class K, class V>
	class map
	{
		struct MapKeyOfT
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
	public:

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

然后给红黑树添加一个模板参数,并修改Insert函数如下:

bool Insert(const T& data)
{
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_col = BLACK;
		return true;
	}
	Node* parent = nullptr;
	Node* cur = _root;
	KeyOfT kot;
	while (cur)
	{
		if (kot(cur->_data) < kot(data))
		{
			parent = cur;
			cur = cur->_right;
		}
		else if (kot(cur->_data) > kot(data))
		{
			parent = cur;
			cur = cur->_left;
		}
		else
		{
			return false;
		}
	}
	cur = new Node(data);
	if (kot(parent->_data) < kot(data))
		parent->_right = cur;
	else
		parent->_left = cur;
	cur->_parent = parent;

	while (parent && parent->_col == RED)
	{
		Node* grandfather = parent->_parent;
		if (grandfather->_left == parent)
		{
			Node* uncle = grandfather->_right;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;
				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
				if (parent->_left == cur)
				{
					RotateR(grandfather);
					grandfather->_col = RED;
					parent->_col = BLACK;
				}
				else
				{
					RotateL(parent);
					RotateR(grandfather);
					grandfather->_col = RED;
					cur->_col = BLACK;
				}
				break;
			}
		}
		else
		{
			Node* uncle = grandfather->_left;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;
				cur = grandfather;
				parent = cur->_parent;
			}
			else
			{
				if (parent->_right == cur)
				{
					RotateL(grandfather);
					grandfather->_col = RED;
					parent->_col = BLACK;
				}
				else
				{
					RotateR(parent);
					RotateL(grandfather);
					grandfather->_col = RED;
					cur->_col = BLACK;
				}
				break;
			}
		}
	}
	_root->_col = BLACK;
	return true;
}

在Insert函数中,我们通过KeyOfT创建出kot对象,然后通过kot()并传入数据对象,该函数会将key返回。这样对于set,传入key返回key,没有变化。对于map传入pair<K, V>,返回pair的first。这样就可以适配map和set的比较了。这里可以说是set迁就于map,因为set本身就是key,但是map需要获取key。
其他函数如Erase、Find修改也是类似的,需要通过KeyOfT创建出kot对象,通过kot()仿函数来获取key进行比较。其他函数请你自行修改。

修改完毕后,可以将map和set的insert函数写出来,然后测试一下。
针对前面的问题:红黑树这里还是需要传入Key的,因为我们在查找、删除函数中需要用到。其他函数代码请你自行修改。


3、实现红黑树的迭代器

这里类似前面的list,由于空间不连续,所以我们需要创建自定义类型。
先来看看库里的实现:

在这里插入图片描述
基本上类似前面list的迭代器实现,只不过红黑树这里迭代器进行++和--会稍微复杂一点。
红黑树的迭代器遍历本质上是中序遍历,因此begin我们返回的是最左节点(最小节点),end我们返回最右节点的下一个数据就是nullptr。
我们先把其他函数写出来,这里的Ref和Ptr就是为了控制实现普通迭代器和const迭代器的。

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)
	{}

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

	Ptr operator->()
	{
		return &(operator*());
	}

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

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

下面我们要实现operator++和operator--:
在这里插入图片描述

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

Self operator++(int)
{
	Self tmp(_node);
	++* this;
	return tmp;
}

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

Self operator--(int)
{
	Self tmp(_node);
	--* this;
	return tmp;
}

紧接着在红黑树中加入如下代码:

typedef __TreeIterator<T, T&, T*> iterator;
typedef __TreeIterator<T, const T&, const T*> const_iterator;

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

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

const_iterator begin() const 
{
	Node* leftMin = _root;
	while (leftMin && leftMin->_left)
		leftMin = leftMin->_left;
	return iterator(leftMin);
}

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

然后在map和set中加入迭代器,就可以配合insert来进行测试了:

typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;

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

iterator end()
{
	return _t.end();
}
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;

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

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

在这里插入图片描述


在这里插入图片描述
上图是库里的实现方式,库里多了一个哨兵位的头节点,左孩子指向树中最左节点(最小节点),右孩子指向树中最右节点(最大节点)。通过这种实现方式可以快速返回begin(),但是也带来了维护较为麻烦的问题。这里了解一下即可。


4、解决map和set中key不可修改问题

测试insert和迭代器通过后,我们还需要解决map和set中key不可修改的问题。而现在我们的迭代器是可以修改的。那么如何实现呢?
在这里插入图片描述
对于set来说,不管是普通迭代器还是const迭代器都是不可修改的,所以直接将const迭代器作为普通迭代器来使用,这是库里的解决方式。

在这里插入图片描述
但是这么写会报错,因此_t还是普通对象,走的还是普通迭代器的begin,调用树的begin返回的也是普通迭代器,所以就出现了普通迭代器无法向const迭代器转换的问题。
处理方式:
1、支持普通迭代器构造const迭代器。
2、类似库里的实现方式。直接在后面加上const。不实现普通类型的迭代器函数了。

在这里插入图片描述
如上图,这样就解决了。


set的问题解决了,下面看map,map能这样实现吗?
答案是不行的,如果这样的话整个pair都不能修改了,不仅key不能修改,value也不能修改。但是我们只要key不可修改,value是可以修改的。
下面看库里的实现方式:

在这里插入图片描述

直接用const将key锁死,这样value还是可以修改的。如下图:
在这里插入图片描述


5、解决insert返回值问题并实现operator[]

之前介绍map和set的使用,insert的返回值是一个pair<iterator, bool>的对象,现在我们需要对红黑树的返回值进行修改,同时实现map的operator[]重载函数。

我们将红黑树的insert函数返回值修改为pair<iterator, bool>,插入成功返回piar<新插入节点的迭代器,true>,插入失败返回pair<已存在节点的迭代器,false>。然后对map和set中insert的返回值进行修改。
修改后运行程序发现:
在这里插入图片描述

这是因为在set这里,无论是iterator还是const_iterator,它们实际上都是const_iterator。而我们的树是普通对象,调用insert之后返回的是普通的迭代器,所以就出现了pair<iterator,bool>向pair<const_iterator,bool>进行转换。但是这里是无法转换的。
我们可以这样处理:

pair<iterator, bool> insert(const K& key)
{
	pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
	return pair<iterator, bool>(ret.first, ret.second);
}

先接受红黑树底层的返回值,然后通过ret.first和ret.second去构造新的pair返回。
但是现在还是无法运行:

在这里插入图片描述
这是因为ret.first是普通迭代器,要构造的pair的first是const迭代器,不支持普通迭代器向const迭代器的转换。所以我们需要实现一个普通迭代器构造const迭代器的函数,如下:
在这里插入图片描述

无论类模板实例化出const迭代器还是普通迭代器,这里的Iterator都是普通迭代器。
1、这个类被实例化为const迭代器时,这个函数是一个构造函数,支持普通迭代器向const迭代器转换。
2、这个类被实例化为普通迭代器时,这个函数是一个拷贝构造函数。


修改了Insert函数的返回值就可以来实现map中operator[]的重载了:

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

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

完整代码

// MySet.h
#pragma once
#include "RBTree.h"

namespace zzy
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
		typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
		iterator begin() const
		{
			return _t.begin();
		}

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

		pair<iterator, bool> insert(const K& key)
		{
			pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(key);
			return pair<iterator, bool>(ret.first, ret.second);
		}
	private:
		RBTree<K, K, SetKeyOfT> _t;
	};
}
// MyMap.h
#pragma once
#include "RBTree.h"

namespace zzy
{
	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;
		typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator const_iterator;

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

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

		const_iterator begin() const
		{
			return _t.begin();
		}

		const_iterator end() const
		{
			return _t.end();
		}

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

		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
			return ret.first->second;
		}
	private:
		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
	};
}
// RBTree.h
#pragma once

enum Colour {
	RED,
	BLACK
};

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

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

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

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

	__TreeIterator(const Iterator& it)
		:_node(it._node)
	{}

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

	Ptr operator->()
	{
		return &(operator*());
	}

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

	Self operator++(int)
	{
		Self tmp(_node);
		++* this;
		return tmp;
	}

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

	Self operator--(int)
	{
		Self tmp(_node);
		--* this;
		return tmp;
	}

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

	bool operator==(const Self& s) const
	{
		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* leftMin = _root;
		while (leftMin && leftMin->_left)
			leftMin = leftMin->_left;
		return iterator(leftMin);
	}

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

	const_iterator begin() const
	{
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)
			leftMin = leftMin->_left;
		return const_iterator(leftMin);
	}

	const_iterator end() const
	{
		return const_iterator(nullptr);
	}


	RBTree()
		:_root(nullptr)
	{}

	RBTree(const RBTree<K, T, KeyOfT>& t)
		:_root(nullptr)
	{
		_root = Copy(t._root, nullptr);
	}

	RBTree<K, T, KeyOfT>& operator=(RBTree<K, T, KeyOfT> t)
	{
		swap(_root, t._root);
		return *this;
	}

	~RBTree()
	{
		Destroy(_root);
	}

	pair<iterator, bool> Insert(const T& data)
	{
		if (_root == nullptr)
		{
			_root = new Node(data);
			_root->_col = BLACK;
			return make_pair(iterator(_root), true);
		}
		Node* parent = nullptr;
		Node* cur = _root;
		KeyOfT kot;
		while (cur)
		{
			if (kot(cur->_data) < kot(data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > kot(data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return make_pair(iterator(cur), false);
			}
		}
		cur = new Node(data);
		if (kot(parent->_data) < kot(data))
			parent->_right = cur;
		else
			parent->_left = cur;
		cur->_parent = parent;
		Node* newnode = cur;
		while (parent && parent->_col == RED)
		{
			Node* grandfather = parent->_parent;
			if (grandfather->_left == parent)
			{
				Node* uncle = grandfather->_right;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (parent->_left == cur)
					{
						RotateR(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
					else
					{
						RotateL(parent);
						RotateR(grandfather);
						grandfather->_col = RED;
						cur->_col = BLACK;
					}
					break;
				}
			}
			else
			{
				Node* uncle = grandfather->_left;
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (parent->_right == cur)
					{
						RotateL(grandfather);
						grandfather->_col = RED;
						parent->_col = BLACK;
					}
					else
					{
						RotateR(parent);
						RotateL(grandfather);
						grandfather->_col = RED;
						cur->_col = BLACK;
					}
					break;
				}
			}
		}
		_root->_col = BLACK;
		return make_pair(iterator(newnode), true);
	}

	bool Erase(const K& key)
	{
		KeyOfT kot;
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (kot(cur->_data) < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (kot(cur->_data) > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				if (cur->_left == nullptr)
				{
					if (_root == cur)
					{
						_root = cur->_right;
						if (_root)
						{
							_root->_parent = nullptr;
							_root->_col = BLACK;
						}
						delete cur;
						return true;
					}
				}
				else if (cur->_right == nullptr)
				{
					if (_root == cur)
					{
						_root = cur->_left;
						if (_root)
						{
							_root->_parent = nullptr;
							_root->_col = BLACK;
						}
						delete cur;
						return true;
					}
				}
				else
				{
					parent = cur;
					Node* rightMin = cur->_right;
					while (rightMin->_left)
					{
						parent = rightMin;
						rightMin = rightMin->_left;
					}
					cur->_data = rightMin->_data;
					cur = rightMin;
				}
				break;
			}
		}
		if (cur == nullptr) return false;
		Node* del = cur;
		Node* delParent = parent;
		if (cur->_col == BLACK && !cur->_left && !cur->_right)
		{
			while (parent)
			{
				if (parent->_left == cur)
				{
					Node* brother = parent->_right;
					if (brother->_col == RED)
					{
						brother->_col = BLACK;
						parent->_col = RED;
						RotateL(parent);
						brother = parent->_right;
					}
					if ((!brother->_left || brother->_left->_col == BLACK)
						&& (!brother->_right || brother->_right->_col == BLACK))
					{
						brother->_col = RED;
						if (parent->_col == RED)
						{
							parent->_col = BLACK;
							break;
						}
						cur = parent;
						parent = cur->_parent;
					}
					else
					{
						if (!brother->_right || brother->_right->_col == BLACK)
						{
							brother->_left->_col = BLACK;
							brother->_col = RED;
							RotateR(brother);
							brother = parent->_right;
						}
						brother->_right->_col = BLACK;
						brother->_col = parent->_col;
						parent->_col = BLACK;
						RotateL(parent);
						break;
					}
				}
				else
				{
					Node* brother = parent->_left;
					if (brother->_col == RED)
					{
						brother->_col = BLACK;
						parent->_col = RED;
						RotateR(parent);
						brother = parent->_left;
					}
					if ((!brother->_left || brother->_left->_col == BLACK)
						&& (!brother->_right || brother->_right->_col == BLACK))
					{
						brother->_col = RED;
						if (parent->_col == RED)
						{
							parent->_col = BLACK;
							break;
						}
						cur = parent;
						parent = cur->_parent;
					}
					else
					{
						if (!brother->_left || brother->_left->_col == BLACK)
						{
							brother->_right->_col = BLACK;
							brother->_col = RED;
							RotateL(brother);
							brother = parent->_left;
						}
						brother->_left->_col = BLACK;
						brother->_col = parent->_col;
						parent->_col = BLACK;
						RotateR(parent);
						break;
					}
				}
			}
		}
		cur = del, parent = delParent;
		if (cur->_left == nullptr)
		{
			if (parent->_left == cur)
				parent->_left = cur->_right;
			else
				parent->_right = cur->_right;
			if (cur->_right)
			{
				cur->_right->_parent = parent;
				cur->_right->_col = BLACK;
			}
		}
		else
		{
			if (parent->_left == cur)
				parent->_left = cur->_left;
			else
				parent->_right = cur->_left;
			if (cur->_left)
			{
				cur->_left->_parent = parent;
				cur->_left->_col = BLACK;
			}
		}
		delete cur;
		return true;
	}

	Node* Find(const K& key)
	{
		KeyOfT kot;
		Node* cur = _root;
		while (cur)
		{
			if (kot(cur->_data) < key)
				cur = cur->_right;
			else if (kot(cur->_data) > key)
				cur = cur->_left;
			else
				return cur;
		}
		return nullptr;
	}

	bool IsBalance()
	{
		return IsBalance(_root);
	}

	int Height()
	{
		return Height(_root);
	}

	void InOrder()
	{
		InOrder(_root);
		cout << endl;
	}

private:
	void InOrder(Node* root)
	{
		if (root == nullptr) return;
		InOrder(root->_left);
		cout << root->_kv.first << " ";
		InOrder(root->_right);
	}

	int Height(Node* root)
	{
		if (root == nullptr) return 0;
		int left = Height(root->_left);
		int right = Height(root->_right);
		return left > right ? left + 1 : right + 1;
	}

	Node* Copy(Node* root, Node* parent)
	{
		if (root == nullptr) return nullptr;
		Node* copy = new Node(root->_kv);
		copy->_col = root->_col;
		copy->_parent = parent;
		copy->_left = Copy(root->_left, copy);
		copy->_right = Copy(root->_right, copy);
		return copy;
	}

	void Destroy(Node*& root)
	{
		if (root == nullptr) return;
		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
		root = nullptr;
	}

	bool IsBalance(Node* root)
	{
		if (root == nullptr) return true;
		if (root->_col != BLACK) return false;
		int benchmark = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLACK) benchmark++;
			cur = cur->_left;
		}
		return CheckColour(root, 0, benchmark);
	}

	bool CheckColour(Node* root, int blacknum, int benchmark)
	{
		if (root == nullptr)
		{
			if (blacknum != benchmark) return false;
			return true;
		}
		if (root->_col == BLACK) blacknum++;
		if (root->_col == RED && root->_parent && root->_parent->_col == RED)
		{
			cout << root->_kv.first << "出现连续的红色节点" << endl;
			return false;
		}
		return CheckColour(root->_left, blacknum, benchmark)
			&& CheckColour(root->_right, blacknum, benchmark);
	}

	void RotateL(Node* parent)
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;
		Node* ppnode = parent->_parent;
		parent->_right = curleft;
		if (curleft)
			curleft->_parent = parent;
		cur->_left = parent;
		parent->_parent = cur;
		if (_root == parent)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
				ppnode->_left = cur;
			else
				ppnode->_right = cur;
			cur->_parent = ppnode;
		}
	}

	void RotateR(Node* parent)
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;
		Node* ppnode = parent->_parent;
		parent->_left = curright;
		if (curright)
			curright->_parent = parent;
		cur->_right = parent;
		parent->_parent = cur;
		if (_root == parent)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
				ppnode->_left = cur;
			else
				ppnode->_right = cur;
			cur->_parent = ppnode;
		}
	}
private:
	Node* _root = nullptr;
};

相关文章:

  • 延迟扩展衰落信道、AWGN、Rayleigh、Rician信道,FMCW雷达的距离、角度、速度信息
  • 前端(vue)学习笔记(CLASS 2):进阶
  • ffmpeg av_find_input_format的作用
  • Windows下不建议使用C/C++运行库的本地化功能
  • transformer架构的语言模型保存的内容与格式详解
  • 【Maven】-- Maven Scope 详解
  • 【一文入门】shell语法进阶篇
  • 鸿蒙next 点击穿透实现
  • org.springframework.boot不存在的其中一个解决办法
  • JAVA面试_进阶部分_Linux面试题
  • Idea 中 Project Structure简介
  • java23种设计模式-中介者模式
  • vue打印页面(可分页、可打印echarts、可显示背景色)
  • Qwen 2.5 技术报告解读
  • leetcode151 反转字符串中的单词
  • Spring Boot 中 @Transactional 注解全面解析
  • MySQL中json类型数据查询
  • 线性回归(一)基于Scikit-Learn的简单线性回归
  • DeepSeek + Higress AI 网关/Spring AI Alibaba 案例征集
  • 博云先进算力管理平台AIOS已上线全尺寸DeepSeek系列模型
  • “上海-日喀则”直飞航线正式通航,将于5月1日开启首航
  • 影子调查|23岁男子驾照拟注销背后的“被精神病”疑云
  • 从 “沪惠保” 到 “沪骑保”看普惠保险的 “上海样式”
  • 王一博赛车故障退赛冲上热搜,工作室回应:下次再战
  • 公交公司须关注新出行需求:“单车巴士”能否常态化
  • 宜家上海徐汇商场明天恢复营业,改造后有啥新变化?