红黑树封装

都知道set与map的底层是红黑树,但是有一个问题,set是普通的去重哈希,map是kv结构,数据类型怎么办?答案是泛型

编程,把这俩看作两个不同的数据类型用模板类实现

enum Color
{
	RED,
	BLACK
};
 
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)
		, _data(data)
		, _col(RED)
	{}
};

map由于也是kv,所以它的insert函数和红黑树是一样的

class map
{
protected:
	typedef RBTreeNode<K, V> Node;
public:
	bool Insert(pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(val);
			_root->_col = BLACK;//根肯定是黑色的
			return true;
		}
		else
		{
			Node* cur = _root;
			Node* parent = nullptr
				while (cur)
				{
					parent = cur;
					if (cur->_val > val)
						cur = cur->left;
					else if (cur->_val < val)
						cur = cur->_right;
					else
						return false;
				}
			cur = new Node(val);
			if (parent->_val.first > cur->_val.first)
			{
				parent->_left = cur;
			}
			else
			{
				parent->_parent = cur;
			}
			cur->_parent = parent;
			///从此处开始进行插入后的调整
			while (parent && parent->_col == RED)//出问题了
			{
				Node* grandparent = parent->_parent;
				Node* uncle = nullptr;
				if (grandparent->_left == parent)//找叔叔分情况
					uncle = grandparent->_right;
				else
					uncle = grandparent->_left;
				if (uncle && uncle->_col == RED)//叔叔是红色的,变色
				{
					parent->_col = BLACK;
					uncle->_col = BLACK;
					grandparent->_col = RED;
					cur = grandparent;
					parent = cur->_parent;
				}
				else if (grandparent->_left == parent)//叔叔是黑色或者不存在,且p是左侧路径,第二
				{
					if (parent->_left = cur)
					{
						RotateR(grandparent);
						grandparent->_col = RED;
						parent->_col = BLACK;
					}
					else//此时p是右侧路径是情况3
					{
						RotateL(parent);
						RotateR(grandparent);
						grandparent->_col = RED;
						cur->_col = BLACK;
					}
				}
				else//叔叔是黑色或者不存在,且p是右侧路径
				{
					if (parent->_right = cur)//情况4
					{
						RotateL(grandparent);
						grandparent->_col = RED;
						parent->_col = BLACK;
					}
					else//情况5
					{
						RotateR(parent);
						RotateL(grandparent);
						grandparent->_col = RED;
						cur->_col = BLACK;
					}
				}
				void RotateL(RBTNode * parent)//左旋
				{
					Node* grandparent = parent->_parent;
					Node* ChildR = parent->_right;
					if (grandparent)
					{
						if (grandparent->_left == parent)
							grandparent->_left = ChildR;
						else
							grandparent->_right = ChildR;
					}
					else
						_root = ChildR;
					ChildR->_parent = grandparent;
					parent->_right = ChildR->_left;
					ChildR->_left->_parent = parent;
					ChildR->_left = parent;
					parent->_parent = ChildR;
				
				}
				void RotateR(RBTNode * parent)//右旋
				{
					Node* grandparent = parent->_parent;
					Node* ChildL = parent->_left;
					if (grandparent)
					{
						if (grandparent->_left == parent)
							grandparent->_left = ChildL;
						else
							grandparent->_right = ChildL;
					}
					else
						_root = ChildL;
					ChildL->_parent = grandparent;
					//两两一组进行改变
					parent->_left = ChildL->_right;
					ChildL->_right->_parent = parent;

					ChildL->_right = parent;
					parent->_parent = ChildL;//
				
				}
		
				
			}

		}
	}
protected:
	Node* _root;
};

set改一下数据类型即可

但是问题来了,pair比较大小和key是不一样的,它先比first再比second,这就不一样了,所以我们要写一个仿函数(一个执行函数功能的类,重载())

template <class K>
class set
{
	struct setkeyof
	{
		const K& operator(const K& key )
		{
			return key;
		}
	};
};
class map
{
protected:
	typedef RBTreeNode<K, pair<K,V>,mapkeyof> Node;
public:
	struct mapkeyof
	{
		const K& operator(const pair<K, V>key)
		{
			return key.first;
		}
	};

相应的红黑树的参数也要把仿函数传进去

普通迭代器

template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T, T&, T*> Iterator;
	typedef RBTreeIterator<T, Ref, Ptr> Self;
	Node* _node;
 
	RBTreeIterator(Node* node)
		: _node(node)
	{}
 
	RBTreeIterator(const Iterator& it)
		: _node(it._node)
	{}
 
	Ref operator*()
	{
		return _node->_data;
	}
 
	Ptr operator->()
	{
		return &(operator*());
	}
 
	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
 
	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
	bool operator=(const Self& s)
	{
		return swap(_node->_data,s._node->_data);
	}
};

迭代器分为两种,普通和const类型,所以它们的返回参数不能一样,为了它们俩可以调用同一个函数,将类模板的参数设置为3个,其中Ref代表const T&,Ptr代表const T*一个是不可修改即二叉搜索树的性质,一个是返回值不可修改即二叉树查找的性质

++运算符重载:右不为空找右子树最左节点,如果为空则一直向上找到根节点或者一个节点,这个节点是它父亲的左子树

Self& operator++()
{
	if (_node->right)//右不为空,找右子树的最左结点
	{
		_node = _node->right;
		while (_node->_left)
			_node = _node->_left;
 
	}
	else//右为空,向上找孩子是父亲左的那个父亲
	{
		while (_node->_parent && _node->_parent->right == _node)
		{
			_node = _node->_parent;
		}
	}
	return *this;
}
Self operator++(int)
{
	Iterator news = this;
	this++:
	return *news;
}

前置返回加之后的引用,后置返回临时对象并给自身调用前置++

--运算符重载:和++相反即可

Self& operator--()//左不为空,找左子树的最右结点
{
	if (_node->left)
	{
		_node=_node->_left
		while (_node->_right)
			_node = _node->right;
	}
	else//左为空,向上找孩子是父亲右的那个父亲
	{
		while (_node->_parent && node->_parent->_left == _node)
			_node = _node->_parent;
		_node = _node->parent;
	}
}
Self& operator--(int)
{
	Self tmp = *this;
	--*this;
	return tmp;
}

红黑树的整体修改

1.成员变量:直接给nullptr,不写构造函数

2.模板参数第一个为K代表参数类型

3.模板参数第二个T可以同时储存键值和键值对

4.模板参数KEYOFT为仿函数,用于获取值

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

5.begin返回最左节点的迭代器,end返回空迭代器

typedef RBTreeIterator<T, T&, T*>iterator;
typedef RBTreeIterator<T, const T&, const T *>const_iterator; 
iterator begin()
{
	Node* cur = _root;
	if (cur == nullptr)
		return iterator(nullptr);
	while (cur->_left)
		cur = cur->_left
		return iterator(cur);
}
const_iterator begin()const
{
	Node* cur = _root;
	if (cur == nullptr)
		return const_iterator(nullptr);
	while (cur->_left)
		cur = cur->_left;
	return const_iterator(cur);
}
iterator end()
{
		return iterator(nullptr);
}
const_iterator end()const
{
		return const_iterator(nullptr);
}

6.find返回迭代器,用KEYOFT作为比较媒介适配map和set

iterator Find(const K& key)
{
	if (_root == nullptr)
	{
		return iterator(nullptr);
	}
 
	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 iterator(cur);
		}
	}
 
	return iterator(nullptr);
}

7.insert返回pair,第一个返回迭代器,后一个返回bool值,用于记录是否插入成功,也要用KEYOFT来比较

pair<iterator, bool> Insert(const T& data)
{
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_col = BLACK;
		return make_pair(iterator(_root), true);
	}
 
	KeyOfT kot;
	Node* parent = nullptr;
	Node* cur = _root;
	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);
		}
	}
 
	Node* newnode = new Node(data);
	cur = newnode;
	if (kot(parent->_data) < kot(data))
	{
		parent->_right = cur;
	}
	else
	{
		parent->_left = cur;
	}
	cur->_parent = parent;
 
	while (parent && parent->_col == RED)
	{
		Node* grandparent = parent->_parent;
		if (grandparent->_right == parent)//uncle在左,parent在右
		{
			Node* uncle = grandparent->_left;
			if (uncle && uncle->_col == RED)//uncle为红,变色+向上调整
			{
				parent->_col = uncle->_col = BLACK;
				grandparent->_col = RED;
 
				cur = grandparent;
				parent = cur->_parent;
			}
			else//uncle为空或为黑,变色+旋转
			{
				if (parent->_right == cur)//左单旋
				{
					RotateL(grandparent);
					parent->_col = BLACK;
					grandparent->_col = RED;
				}
				else//右左旋
				{
					RotateR(parent);
					RotateL(grandparent);
					cur->_col = BLACK;
					grandparent->_col = RED;
				}
			}
		}
		else//parent在左,uncle在右
		{
			Node* uncle = grandparent->_right;
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandparent->_col = RED;
 
				cur = grandparent;
				parent = cur->_parent;
			}
			else
			{
				if (parent->_left == cur)//右单旋
				{
					RotateR(grandparent);
					parent->_col = BLACK;
					grandparent->_col = RED;
				}
				else//左右旋
				{
					RotateL(parent);
					RotateR(grandparent);
					cur->_col = BLACK;
					grandparent->_col = RED;
				}
			}
		}
	}
	_root->_col = BLACK;
 
	return make_pair(iterator(newnode), true);
}

set

KEYOFT直接返回key,且K和T是一样的

template<class K>
class set
{
	struct SetKeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
public:
protected:
	RBTree<K, K, SetKeyOfT> _t;
};

begin和end

set的key不允许修改,所以set的迭代器和const迭代器的底层都是红黑树的const迭代器

begin()返回的迭代器类型是const类型,但是红黑树里面的begin返回的是普通类型,所以要拷贝构造,进行类型转换

typedef RBTree<K,K,SetKeyOfT>::const_iterator iterator;
typedef RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
iterator begin()
{
	return _t.begin();
}
const_iterator begin()const
{
	return _t.begin();
}
iterator end()
{
	return _t.end();
}
const_iterator end()const
{
	return _t.end();
}

find

iterator find(const K& key)
{
	return _t.Find(key);
}

insert

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

map

仿函数返回first,T的类型是pair

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

begin和end

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

find

map不允许修改key,所以除了属于const迭代器以外要对key进行修饰

iterator find(const K& key)
{
	return _t.Find(key);
}

insert

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

operator[]

返回值可以直接修改second

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值