目录

封装set和map的红黑树的实现

迭代器的实现

红黑树成员函数的实现

接下来在红黑树中实现插入

接下来要解决map和set中key不能修改的问题:

map中的成员函数operator[]

实现红黑树的默认成员函数


以前的set和map实现要自己写两颗RBTree,因为set中存储的是key,map中存储的是pair,现在我们对set和map进行封装,也就是使用同一个模板RBTree让编译器实例化出set和map两个类

通过给set和map传入不同的模板参数,在各自的类里实例化出参数个数相同但参数类型不同的红黑树

我们先看源代码

set的第二个模板参数为value_type,类型是Key;map的第二个模板参数为value_type,类型是pair<const Key,T>。注意:T为单个数值的类型(我们常说的value),value_type(pair)为红黑树节点存储的数据类型

我们再往深挖一下

我们可以看到源码中rb_tree有5个模板参数,通过传入不同的Value(key/pair<key,value>)来实现存储数据的类型不同,进而实现对set和map的不同实例化。

第一个困境:

为什么BTree类的第二个模板参数Value中包含key,但还要传入第一个key模板参数呢?

如果是insert(const Value& v)就刚刚好,但如果是find(const Key& key),得传入key,因此就需要第一个模板参数。

第二个困境:

为什么BTree类的第二个模板参数Value中包含key,但还要传入第三个模板参数仿函数KeyOfT,来取出Value中的key呢?

比如 Insert(const Value& data) BTreeNode<Value>* cur=_root;(Value可能是key/pair)

我们当然可以通过第二个模板参数Value从中这样取出key(set:cur->_data(Value--key);map:cur->_data.first(Value.first--key))但是BRTree模板的代码只有一份,我们得统一形式;

所以使用一个仿函数KeyOfT,来取出 data中的key,KeyOfT(cur->_data),这样将Key作为形参时,代码就相同了。

封装set和map的红黑树的实现

我们对红黑树的框架进行修改,修改成模板

这里key用K,value用V,红黑树节点中存储的的类型用T,T可能是key/pair

这里我们不知道红黑树节点中存储的数据类型是啥,因此对T实现泛型

1.我们先对RBTreeNode红黑树节点修改

将存储的数据类型泛化为T,T可能是set存储的key,也可能是map存储的pair,就看set/map的模板参数传啥实例化了

2.接着对RBTree修改

如上文所说,红黑树还需要实现find/erase,需要通过key来实现,因此增加第一个模板参数Key;插入insert时,形参传入T,第一步得通过T中的key找到待插入的位置,但下层红黑树内部RBTree不知道是传入的T data是key还是pair,但是上层set/map中知道T的类型,在外部定义仿函数,然后传给BTree模板,因此增加第三个模板参数,取出T中的key,通过仿函数来实现。

先通过insert理解一下仿函数的作用

insert插入得先通过Key找到待插入的位置,通过不同类中的仿函数,取出T中的Key。

可以直接比较cur->_data与data吗?

传入set比较K,传入map比较pair也挺好的呀,

但cur->_data不能与data直接比较,因为data的类型不知到是K,还是pair;是K那就直接比较,但如果是pair,它的比较逻辑是比完K还要比value

因此我们需要实现仿函数KeyOfValue直接取出value中的K。

迭代器的实现

用一个迭代器类型RBTreeIterator封装节点的指针,这个类中再加上其他成员函数,重载运算符来实现

先定义一个迭代器的类

template<class T, class Ref, class Ptr>//T,T&,T*
struct RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;

	Node* _node;//当前节点

	RBTreeIterator(Node* node)
		:_node(node)
	{ }
};

当前迭代器中包含一个成员,当前迭代器所处节点_node.

为了让迭代器像指针一样使用,先对*,->进行运算符重载

//模拟指针解引用,返回迭代器当前指向节点中存储的元素值的引用
Ref operator*()
{
	return _node->_data;
}

//模拟指针的成员访问,当存储的是结构体时,直接访问对象的成员,返回元素的指针。
Ptr operator->()
{
	return &_node->_data;
}

//判断两个迭代器是否指向同一个节点(即是否指向容器中的同一个元素)。
operator==((const Self& s) const
{
	return _node == s._node;
}

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

在RBTree中实现

1.begin(),返回首元素的迭代器,也就是二叉搜索树中的最小元素,在最左边。

2.end(),返回最后一个元素的下一个位置,也就是nullptr

//迭代器
template<class T, class Ref, class Ptr>//T,T&,T*
struct RBTreeIterator
{
	typedef RBTNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;
    typedef RBTreeIterator<T, const T&, const T*> ConstIterator;

	Node* _node;//当前节点

	RBTreeIterator(Node* node)
		:_node(node)
	{ }
};

template<class K, class T, class KeyOfT>
class RBTree
{
	typedef RBNode<T> Node;
	typedef RBTreeIterator<T, T&, T*> Iterator;
public:
	Iterator Begin()
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return Iterator(cur);
	}

	Iterator End()
	{
		return Iterator(nullptr);
	}
private:
	Node* _root = nullptr;
};

const迭代器也是如此,在旁边加上const修饰,保证this指向的对象的内容不能被修改

	ConstIterator Begin() const//const保证this指针指向的对象内容不能被修改
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return ConstIterator(cur);
	}

	ConstIterator End() const
	{
		return ConstIterator(nullptr);
	}

迭代器类中实现

operator++(),红黑树走中序遍历(左子树-根-右子树),++意味着当前节点已经访问完,该访问的下一个节点是右子树的中序的第一个。

因此有两种情况:

1.该节点有右子树,访问右子树的最左节点

2.该节点的右子树为空,说明以该节点为根的子树已经遍历完了,又分为两种情况

1)当前的子树是父亲的左子树,那++之后就该遍历这个父节点了

2)当前的子树是父亲的右子树,说明父亲和父亲的右和左已经遍历完,以父节点为根的子树已经遍历完;然后循环判断 以父节点为根的子树 是祖父的左还是右,如果是左的话,就遍历祖父节点,如果是右的话,那就说明以祖父节点为根节点的子树已经遍历完。一直循环,最差_node到根节点,父亲为nullptr(此时++,迭代器指向有效元素的下一个位置,返回null迭代器)。

Self operator++()
{
	if (_node->_right != nullptr)//右子树不为空,找右子树的最左节点
	{
		Node* min = _node->_right;//minright!=nullptr
		while (min->_left)
		{
			min = min->_left;
		}
		_node = min;
	}
	else//右子树为空
	{
		Node* cur = _node;
		Node* parent = cur->_parent;
		while (parent && parent->_right == _node)//最差到根节点
		{
			_node = parent;
            parent = parent->_parent;
		}
		_node = parent;//即使parent==null,说明_node 为根,++后返回迭代器末尾null也合理
	}
	return *this;//返回的是该对象的迭代器,迭代器内部的当前节点_node改成parent,相当于移动了
}

operator--(),红黑树走中序遍历,--之后遍历当前节点的左子树的最大值(左子树的最右边/左子树中序遍历的最后一个)

分两种情况:

1.该节点有左子树,访问左子树的最右节点

2.该节点没有左子树,--表示要找比当前节点更小的值,但以当前节点为根的子树已经不可能存在;当前节点是父亲的右节点,那就返回父亲;当前节点是父亲的左节点,继续循环,如果父亲是祖父的右节点,返回祖父,如果父亲是祖父的左节点,还需继续返回到上一层。一直循环,最差到根节点。(此时_node--,返回null迭代器)

这种情况有点特殊,在迭代器内部应该引入一个新的成员变量_root,因为如果是--end()的话,当前_node = nullptr,应该返回最大的有效元素,也就是树的最右边的节点,此时就需要根节点_root寻找最右边的节点。

Self operator--()
{
	//_node=nullptr,也就是--end
	//迭代器中只有当前所处节点,现在成员中应该加上根节点
	if (_node == nullptr)
	{
		Node* max = _root;//找右子树的最大值
		while (max->_right)
		{
			max = max->_right;
		}
		_node = max;
	}
	
	//左不为空,找左子树中的最大值
	else if(_node->_left)
	{
		Node* max = _root->_left;
		while (max->_right)
		{
			max = max->_right;
		}
		_node = max;
	}
	else
	{
		Node* parent = _node->_parent;
		while (parent && parent->_left==_node)
		{
			_node = parent;
			parent = parent->_parent;
		}
		_node = parent;
	}
	return *this;
}

所以,最终的迭代器类框架应该长这样:

template<class T,class Ref,class Ptr>
struct RBTreeIterator
{
	typedef RBNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;
	
	Node* _node;//当前迭代器所处节点
	Node* _root;//根节点,--end
	RBTreeIterator(Node* node,Node* root)
		:_node(node)
		,_root(root)
	{ }
};

有两个成员变量,那其他的函数应该跟随改动,也就是初始化迭代器的时候传入当前节点和根节点。

红黑树成员函数的实现

接下来在红黑树中实现插入

1.先通过仿函数找到key进而找到插入位置

2.红黑树的插入逻辑

bool Insert(const T& data)
{
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_color = BLACK;

		return 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 false;
		}
	}
	cur = new Node(data);
	//开始插入,parent为红,grandfather为黑,uncle为红,cur为红
	cur->_color = RED;
	//链接节点
	//判断这新节点cur插入到parent的左边还是右边
	if (kot(cur->_data) < kot( parent->_data))
	{
		parent->_left = cur;
	}
	else
	{
		parent->_right = cur;
	}
	cur->_parent = parent;
	//调整颜色
	//父亲的颜色为红
	while (parent && parent->_color == RED)
	{
		Node* grandparent = parent->_parent;//parent必存在,否则parent为根

		//先判断父亲在爷爷的左边还是右边,这样才能确定u的位置
		if (grandparent->_left == parent)
		{
			//  g
			//p   u
			Node* uncle = grandparent->_right;

			//情况1
			//叔叔存在,且叔叔的颜色为红
			if (uncle && uncle->_color == RED)
			{
				parent->_color = BLACK;
				uncle->_color = BLACK;
				//爷爷肯定为黑,把它变红
				grandparent->_color = RED;
				//继续向上处理
				cur = grandparent;
				parent = cur->_parent;
			}
			//情况2,叔叔不存在,或者叔叔存在但颜色为黑
			else
			{
				//已知p为g的左边,判断c是否为p的左边
				if (parent->_left == cur)
				{
					//g进行右单旋
					RotateR(grandparent);
					//变色,p变黑,g变红
					parent->_color = BLACK;
					grandparent->_color = RED;
				}
				else//p在g的左边,c在p的右边
				{
					//进行双旋
					RotateL(parent);
					RotateR(grandparent);
					//接着变色,c变黑,g变红
					cur->_color = BLACK;
					grandparent->_color = RED;
				}
				break;
			}
		}

		else//父亲在爷爷的右边
		{
			Node* uncle = grandparent->_left;//叔叔在爷爷的左边
			//情况1,叔叔存在且为红
			if (uncle && uncle->_color == RED)
			{
				//变色,不用旋转
				parent->_color = BLACK;
				grandparent->_color = RED;
				uncle->_color = BLACK;

				//继续向上处理
				cur = grandparent;
				parent = cur->_parent;
			}
			//情况2,叔叔不存在;或者叔叔存在且为黑
			//旋转+变色
			else
			{
				//单旋
				if (parent->_right == cur)//cur在parent的右边
				{
					//左旋
					RotateL(grandparent);
					//变色
					parent->_color = BLACK;
					grandparent->_color = RED;
				}
				//双旋
				else//cur在parent的左边
				{
					//parent右旋
					RotateR(parent);
					//grandfather左旋
					RotateL(grandparent);
					//变色
					cur->_color = BLACK;
					grandparent->_color = RED;
				}
				break;
			}
		}
	}
	//直接将_root变成黑色
	_root->_color = BLACK;
	return true;
}

接下来要解决map和set中key不能修改的问题:

只需要在set和map类里分别传入不同的const模板参数来实例化出不能修改的key红黑树就行

set的iterator不支持修改,那就将set的第二个模板参数K改成const K;map的iterator不支持修改K,但支持修改value,将pair的第1个模板参数改为const K

set:RBTree<K,K, SetKeyOfT> _t  改成  RBTree<K,const K, SetKeyOfT> _t;

map:RBTree<K, pair<K, V>, MapKeyOfT> _t  改成  RBTree<K, pair<const K, V>, MapKeyOfT> _t;

注意也要将这里的重命名修改一下,加const,避免实例化出来的end中iterator与Iterator类型不匹配。

map中的成员函数operator[]

map中的 [] 是通过insert实现的

当key存在时,返回已存在元素值的引用,当然也可以修改

当key不存在时,插入一个以key为键,对应值为默认构造的元素

1.首先先修改insert

将返回值改成pair<iterator,bool>,

pair<Iterator,bool> Insert(const T& data)
{
//1.不存在,则插入
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_color = BLACK;

		//return pair<Iterator, bool>(Iterator(_root), true);
		return { Iterator(_root,_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
		{
//2.存在,返回已经存在的节点
			return { Iterator(cur,_root), false };
		}
	}
	cur = new Node(data);
	Node* newnode = cur;
	//开始插入,parent为红,grandfather为黑,uncle为红,cur为红
	cur->_color = RED;
	//链接节点
	//判断这新节点cur插入到parent的左边还是右边
	if (kot(cur->_data) < kot(parent->_data))
	{
		parent->_left = cur;
	}
	else
	{
		parent->_right = cur;
	}
	cur->_parent = parent;
	//调整颜色
	//父亲的颜色为红
	while (parent && parent->_color == RED)
	{
		Node* grandparent = parent->_parent;//parent必存在,否则parent为根

		//先判断父亲在爷爷的左边还是右边,这样才能确定u的位置
		if (grandparent->_left == parent)
		{
			//  g
			//p   u
			Node* uncle = grandparent->_right;

			//情况1
			//叔叔存在,且叔叔的颜色为红
			if (uncle && uncle->_color == RED)
			{
				parent->_color = BLACK;
				uncle->_color = BLACK;
				//爷爷肯定为黑,把它变红
				grandparent->_color = RED;
				//继续向上处理
				cur = grandparent;
				parent = cur->_parent;
			}
			//情况2,叔叔不存在,或者叔叔存在但颜色为黑
			else
			{
				//已知p为g的左边,判断c是否为p的左边
				if (parent->_left == cur)
				{
					//g进行右单旋
					RotateR(grandparent);
					//变色,p变黑,g变红
					parent->_color = BLACK;
					grandparent->_color = RED;
				}
				else//p在g的左边,c在p的右边
				{
					//进行双旋
					RotateL(parent);
					RotateR(grandparent);
					//接着变色,c变黑,g变红
					cur->_color = BLACK;
					grandparent->_color = RED;
				}
				break;
			}
		}

		else//父亲在爷爷的右边
		{
			Node* uncle = grandparent->_left;//叔叔在爷爷的左边
			//情况1,叔叔存在且为红
			if (uncle && uncle->_color == RED)
			{
				//变色,不用旋转
				parent->_color = BLACK;
				grandparent->_color = RED;
				uncle->_color = BLACK;

				//继续向上处理
				cur = grandparent;
				parent = cur->_parent;
			}
			//情况2,叔叔不存在;或者叔叔存在且为黑
			//旋转+变色
			else
			{
				//单旋
				if (parent->_right == cur)//cur在parent的右边
				{
					//左旋
					RotateL(grandparent);
					//变色
					parent->_color = BLACK;
					grandparent->_color = RED;
				}
				//双旋
				else//cur在parent的左边
				{
					//parent右旋
					RotateR(parent);
					//grandfather左旋
					RotateL(grandparent);
					//变色
					cur->_color = BLACK;
					grandparent->_color = RED;
				}
				break;
			}
		}
	}
	//直接将_root变成黑色
	_root->_color = BLACK;
//3.不存在,直接插入,返回包含新节点迭代器和 true 的 pair
	return { Iterator(newnode,_root), true };;
}

2.紧接着实现operator[],返回map中,pair中,value的引用

V& operator[](const K& key)
{
	pair<iterator, bool> ret = insert({ key,V() });
	return ret.first->second;
}
sxm::map<string,string> ss;
ss["right"];//不存在则插入;ss["right"];为operator[]返回的值的引用,可以进行修改
ss["left"] = "左边";//插入新节点
ss["left"] = "左边,剩余";//对存在的节点修改

实现红黑树的默认成员函数

class BTree
{
    public:
        //默认成员函数
        //1.构造函数
        RBTree() = default;

        //2.析构函数
        ~RBTree()
        {
	        Destory(_root);
	        _root = nullptr
        }
        //3.拷贝构造函数
        RBTree(const RBTree<T>& rb)
        {
	        _root = CopeTree(rb._root, nullptr);
        }

    private:
    	Node* _root = nullptr;

	    void Destory(Node* root)
	    {
	    	//递归结束条件
	    	if (root == nullptr)
		    	return;

		    Destory(root->_left);
		    Destory(root->_right);
		    delete root;
		    root = nullptr;
	    }

	    //递归复制以node为根的子树,返回新子树的根
	    
	    Node* CopeTree(Node* node, Node* parent)//这一层的新节点node,与上一层的parent
	    {
	    	//递归结束条件
	    	if (node == nullptr)
	    		return nullptr;
	    	//建立新节点
	    	Node* newnode = new Node(node->_data);
	    	newnode->_color = node->_color;

	    	newnode->_left = CopyTree(node->_left, newnode);//对于node->_left来说,newnode为它的父亲
	    	newnode->_right = CopyTree(node->_right, newnode);

	    	return newnode;
	    }
};

总代码

myset.h

#pragma once
#include "RBTree2.h"

namespace sxm
{
	template<class K>
	class set
	{
		struct SetKeyOfT
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
	public:
		typedef typename RBTree<K,const K, SetKeyOfT>::Iterator iterator;
		typedef typename RBTree<K,const K, SetKeyOfT>::ConstIterator 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 K& key)
		{
			return _t.Insert(key);
		}
	private:
		RBTree<K,const K, SetKeyOfT> _t;
	};
}

mymap.h

#pragma once
#include "RBTree2.h"

namespace sxm
{
	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>::ConstIterator 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 = insert({ key,V() });
			return ret.first->second;
		}
	private:
		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
	};
}

RBTree2.h

#pragma once
#include<iostream>
using namespace std;

enum Color
{
	RED,
    BLACK
};

template<class T>
struct RBNode
{
	T _data;

	RBNode<T>* _left;
	RBNode<T>* _right;
	RBNode<T>* _parent;
	Color _color;

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

template<class T,class Ref,class Ptr>
struct RBTreeIterator
{
	typedef RBNode<T> Node;
	typedef RBTreeIterator<T, Ref, Ptr> Self;
	
	Node* _node;//当前迭代器所处节点
	Node* _root;//根节点,--end
	RBTreeIterator(Node* node,Node* root)
		:_node(node)
		,_root(root)
	{ }

	Ref operator*()
	{
		return _node->_data;
	}
	Ptr operator->()
	{
		return &_node->_data;
	}
	bool operator!= (const Self& s) const
	{
		return _node != s._node;
	}
	bool operator== (const Self& s) const
	{
		return _node == s._node;
	}

	Self operator++()
	{
		if (_node->_left)
		{
			//右不为空
			Node* min = _node->_right;
			while (min->_left)
			{
				min = min->_left;
			}
			_node = min;
		}
		else
		{
			//右为空
			Node* parent = _node->_parent;
			while (parent && parent->_right == _node)
			{
				_node = parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}
	Self operator--()
	{
		//_node=nullptr,也就是--end
		//迭代器中只有当前所处节点,现在成员中应该加上根节点
		if (_node == nullptr)
		{
			Node* max = _root;//找右子树的最大值
			while (max->_right)
			{
				max = max->_right;
			}
			_node = max;
		}
		
		//左不为空,找左子树中的最大值
		else if(_node->_left)
		{
			Node* max = _root->_left;
			while (max->_right)
			{
				max = max->_right;
			}
			_node = max;
		}
		else
		{
			Node* parent = _node->_parent;
			while (parent && parent->_left==_node)
			{
				_node = parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}
};

template<class K,class T,class KeyOfT>
class RBTree
{
	typedef RBNode<T> Node;
public:
	typedef RBTreeIterator<T, T&, T*> Iterator;
	typedef RBTreeIterator<T, const T&, const T*> ConstIterator;

	Iterator Begin()
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return Iterator(cur,_root);
	}

	Iterator End()
	{
		return Iterator(nullptr,_root);
	}

	Iterator Begin() const
	{
		Node* cur = _root;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return ConstIterator(cur,_root);
	}

	Iterator End() const
	{
		return ConstIterator(nullptr,_root);
	}

pair<Iterator,bool> Insert(const T& data)
{
	if (_root == nullptr)
	{
		_root = new Node(data);
		_root->_color = BLACK;

		//return pair<Iterator, bool>(Iterator(_root), true);
		return { Iterator(_root,_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 { Iterator(cur,_root), false };
		}
	}
	cur = new Node(data);
	Node* newnode = cur;
	//开始插入,parent为红,grandfather为黑,uncle为红,cur为红
	cur->_color = RED;
	//链接节点
	//判断这新节点cur插入到parent的左边还是右边
	if (kot(cur->_data) < kot(parent->_data))
	{
		parent->_left = cur;
	}
	else
	{
		parent->_right = cur;
	}
	cur->_parent = parent;
	//调整颜色
	//父亲的颜色为红
	while (parent && parent->_color == RED)
	{
		Node* grandparent = parent->_parent;//parent必存在,否则parent为根

		//先判断父亲在爷爷的左边还是右边,这样才能确定u的位置
		if (grandparent->_left == parent)
		{
			//  g
			//p   u
			Node* uncle = grandparent->_right;

			//情况1
			//叔叔存在,且叔叔的颜色为红
			if (uncle && uncle->_color == RED)
			{
				parent->_color = BLACK;
				uncle->_color = BLACK;
				//爷爷肯定为黑,把它变红
				grandparent->_color = RED;
				//继续向上处理
				cur = grandparent;
				parent = cur->_parent;
			}
			//情况2,叔叔不存在,或者叔叔存在但颜色为黑
			else
			{
				//已知p为g的左边,判断c是否为p的左边
				if (parent->_left == cur)
				{
					//g进行右单旋
					RotateR(grandparent);
					//变色,p变黑,g变红
					parent->_color = BLACK;
					grandparent->_color = RED;
				}
				else//p在g的左边,c在p的右边
				{
					//进行双旋
					RotateL(parent);
					RotateR(grandparent);
					//接着变色,c变黑,g变红
					cur->_color = BLACK;
					grandparent->_color = RED;
				}
				break;
			}
		}

		else//父亲在爷爷的右边
		{
			Node* uncle = grandparent->_left;//叔叔在爷爷的左边
			//情况1,叔叔存在且为红
			if (uncle && uncle->_color == RED)
			{
				//变色,不用旋转
				parent->_color = BLACK;
				grandparent->_color = RED;
				uncle->_color = BLACK;

				//继续向上处理
				cur = grandparent;
				parent = cur->_parent;
			}
			//情况2,叔叔不存在;或者叔叔存在且为黑
			//旋转+变色
			else
			{
				//单旋
				if (parent->_right == cur)//cur在parent的右边
				{
					//左旋
					RotateL(grandparent);
					//变色
					parent->_color = BLACK;
					grandparent->_color = RED;
				}
				//双旋
				else//cur在parent的左边
				{
					//parent右旋
					RotateR(parent);
					//grandfather左旋
					RotateL(grandparent);
					//变色
					cur->_color = BLACK;
					grandparent->_color = RED;
				}
				break;
			}
		}
	}
	//直接将_root变成黑色
	_root->_color = BLACK;
	return { Iterator(newnode,_root), true };;
}

//bool Insert(const T& data)
//{
//	if (_root == nullptr)
//	{
//		_root = new Node(data);
//		_root->_color = BLACK;
//
//		return 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 false;
//		}
//	}
//	cur = new Node(data);
//	//开始插入,parent为红,grandfather为黑,uncle为红,cur为红
//	cur->_color = RED;
//	//链接节点
//	//判断这新节点cur插入到parent的左边还是右边
//	if (kot(cur->_data) < kot( parent->_data))
//	{
//		parent->_left = cur;
//	}
//	else
//	{
//		parent->_right = cur;
//	}
//	cur->_parent = parent;
//	//调整颜色
//	//父亲的颜色为红
//	while (parent && parent->_color == RED)
//	{
//		Node* grandparent = parent->_parent;//parent必存在,否则parent为根
//
//		//先判断父亲在爷爷的左边还是右边,这样才能确定u的位置
//		if (grandparent->_left == parent)
//		{
//			//  g
//			//p   u
//			Node* uncle = grandparent->_right;
//
//			//情况1
//			//叔叔存在,且叔叔的颜色为红
//			if (uncle && uncle->_color == RED)
//			{
//				parent->_color = BLACK;
//				uncle->_color = BLACK;
//				//爷爷肯定为黑,把它变红
//				grandparent->_color = RED;
//				//继续向上处理
//				cur = grandparent;
//				parent = cur->_parent;
//			}
//			//情况2,叔叔不存在,或者叔叔存在但颜色为黑
//			else
//			{
//				//已知p为g的左边,判断c是否为p的左边
//				if (parent->_left == cur)
//				{
//					//g进行右单旋
//					RotateR(grandparent);
//					//变色,p变黑,g变红
//					parent->_color = BLACK;
//					grandparent->_color = RED;
//				}
//				else//p在g的左边,c在p的右边
//				{
//					//进行双旋
//					RotateL(parent);
//					RotateR(grandparent);
//					//接着变色,c变黑,g变红
//					cur->_color = BLACK;
//					grandparent->_color = RED;
//				}
//				break;
//			}
//		}
//
//		else//父亲在爷爷的右边
//		{
//			Node* uncle = grandparent->_left;//叔叔在爷爷的左边
//			//情况1,叔叔存在且为红
//			if (uncle && uncle->_color == RED)
//			{
//				//变色,不用旋转
//				parent->_color = BLACK;
//				grandparent->_color = RED;
//				uncle->_color = BLACK;
//
//				//继续向上处理
//				cur = grandparent;
//				parent = cur->_parent;
//			}
//			//情况2,叔叔不存在;或者叔叔存在且为黑
//			//旋转+变色
//			else
//			{
//				//单旋
//				if (parent->_right == cur)//cur在parent的右边
//				{
//					//左旋
//					RotateL(grandparent);
//					//变色
//					parent->_color = BLACK;
//					grandparent->_color = RED;
//				}
//				//双旋
//				else//cur在parent的左边
//				{
//					//parent右旋
//					RotateR(parent);
//					//grandfather左旋
//					RotateL(grandparent);
//					//变色
//					cur->_color = BLACK;
//					grandparent->_color = RED;
//				}
//				break;
//			}
//		}
//	}
//	//直接将_root变成黑色
//	_root->_color = BLACK;
//	return true;
//}

	//右单旋
	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		//b链接到10的左子树
		parent->_left = subLR;
		if (subLR)
			//前提是subLR!=nullptr
			//更改subLR的父亲
			subLR->_parent = parent;

		//记录一下parent->_parent
		Node* pparent = parent->_parent;

		//10链接到5的右子树
		subL->_right = parent;
		parent->_parent = subL;

		//parent的父节点也得指向新的孩子
		//parent有两种情况,1.parent本身是根节点,没有父节点,不用改变父节点的指向,直接改变根节点
		//2.parent不是根节点,改变父亲的指向parent->_parent->_left/_right=subL

		if (parent == _root)
		{
			_root = subL;
			subL->_parent = nullptr;//改变subL的父节点
		}
		else
		{
			if (pparent->_left == parent)
			{
				pparent->_left = subL;
			}
			else
			{
				pparent->_right = subL;
			}
			subL->_parent = pparent;
		}

	}

	//左单旋
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		//将b链接到10的右子树
		parent->_right = subRL;

		if (subRL)
			//前提subRL!=nullptr
			//更新b的父亲
			subRL->_parent = parent;

		//记录parent的父亲
		Node* pparent = parent->_parent;

		//将10链接到15的左边
		subR->_left = parent;

		//更新10的父亲
		parent->_parent = subR;

		//如果parent不为_root的话,要注意parent->_parent的孩子已经改变
		//如果parent为根的话,更新根
		if (parent == _root)
		{
			_root = subR;
			subR->_parent = nullptr;
		}
		else
		{
			if (pparent->_left == parent)
			{
				pparent->_left = subR;
			}
			else
				pparent->_right = subR;
			subR->_parent = pparent;
		}
	}

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

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

	int Size()
	{
		return _Size(_root);
	}
	
private:

	//高度
	int _Height(Node* root)
	{
		//递归结束条件
		if (root == nullptr)
		{
			return 0;
		}
		int leftheight = _Height(root->_left);
		int rightheight = _Height(root->_right);
		return leftheight > rightheight ? leftheight + 1 : rightheight + 1;
	}

	//总节点个数
	int _Size(Node* root)
	{
		if (root == nullptr)
		{
			return 0;
		}
		int leftsize = _Size(root->_left);
		int rightsize = _Size(root->_right);
		return leftsize + rightsize + 1;
	}

	Node* _root = nullptr;
};

感谢阅读!

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐