set与map的详细封装步骤

目录

一.set与map在STL中的源码

二.修改红黑树

1.插入与查找时的比较方式

2.插入时的返回值

3.补充成员函数

三.封装set与map

1.迭代器的实现

2.函数接口

3.map中的operator[]

四.完整代码

set.h

map.h

RBTree.h


一.set与map在STL中的源码

想要简单实现set与map 需要我们稍微理解其底层代码。以下是简化部分

set:

template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:
  // typedefs:
 
  typedef Key key_type;
  typedef Key value_type;
  typedef Compare key_compare;
  typedef Compare value_compare;
private:
  typedef rb_tree<key_type, value_type, 
                  identity<value_type>, key_compare, Alloc> rep_type;
  rep_type t;  // red-black tree representing set
  //·····
}

map:

template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:
 
// typedefs:
 
  typedef Key key_type;
  typedef T data_type;
  typedef T mapped_type;
  typedef pair<const Key, T> value_type;
  typedef Compare key_compare;
    
//·····
 
private:
  typedef rb_tree<key_type, value_type, 
                  select1st<value_type>, key_compare, Alloc> rep_type;
  rep_type t;  // red-black tree representing map
 
//·····
}

从两者私有部分不难看出,两者的底层都使用了红黑树。但一棵红黑树只能为K-V模型或K模型,那是如何同时满足map的K-V模型和set的K模型的呢?

不难看出,set与map虽然共用了一颗红黑树,但传入值的方式不一样

set传入的为<K,K>, map传入的是<K, pair<const K, V> >

关于两类模板参数,第一个K方便find和erase接口,第二个则决定我们的红黑树是那种模型,那怎样将两种模型泛化到一起呢?

由于用户只能从上层调用接口,我们在底层添加模板参数T,set对于T传入K,map对于T传入

pari<const K, V>。具体如下

set:

template<class K>
class set
{

public:

private:

	RBTree<K, const K, SetKeyOfT> _t;
};

map:

template<class K, class V>
class map
{

public:

private:
	// key不能修改(第一个k为什么不加const?
	//第一个K 只用于删除和查找, 外层修改不到。
	RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};

RBTree:

enum Colour
{
	RED,   //0
	BLACK  //1
};

//RBTree树节点
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;

public:

private:
	Node* _root = nullptr;
};

二.修改红黑树

1.插入与查找时的比较方式

当我们插入元素时,set插入的元素为K,比较大小时可以直接比较,map插入的元素为pair<K,V>,在C++中pair直接比较则会首先按照first的大小比较,first相同时再按照second大小比较,这显然不是我们期望的只用K关键字比较。那么如何才能使用一种统一的方式解决这个问题呢?

采用仿函数

在map和set类中添加各自的仿函数,其功能是拿到各自的Key,便于红黑树的比较。

set:

template<class K>
class set
{
	//仿函数  因为map中红黑树的T 为pair, set中为K, 为了泛型编程
	//我们使用仿函数对map和set进行统一处理
	struct SetKeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
public:


private:

	RBTree<K, const K, SetKeyOfT> _t;
};

map:

template<class K, class V>
class map
{
	//仿函数  因为map中红黑树的T 为pair, set中为K, 为了泛型编程
	//我们使用仿函数对map和set进行统一处理
	struct MapKeyOfT
	{
		const K& operator()(const pair<K, V>& kv)
		{
			return kv.first;
		}
	};
public:


private:
	// key不能修改(第一个k为什么不加const?
	//第一个K 只用于删除和查找, 外层修改不到。
	RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};

RBTree:模板中添加仿函数

enum Colour
{
	RED,   //0
	BLACK  //1
};

//RBTree树节点
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 KeyOfT>
class RBTree
{
	typedef RBTreeNode<T> Node;

public:

private:
	Node* _root = nullptr;
};

2.插入时的返回值

在C++源码中, set与map插入的返回值都是pair类型:其意为如果插入成功与否,都返回一个pair类型,如果成功则返回插入位置的迭代器与true,如果失败则返回重复元素位置的迭代器与false。所以,我们应修改Insert函数的返回值。

完善后的Insert函数(内含的迭代器部分在下面会讲,先关注返回值与比较部分即可):

//插入成功--->返回插入位置和true
//插入失败--->返回该元素存在的位置和false
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)
	{
		// K
		// pair<K, V>
		// kot对象,是用来取T类型的data对象中的key
		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);
	cur->_col = RED;
	//记录cur位置
	Node* newnode = cur;

	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 (parent == grandfather->_left)
		{
			Node* uncle = grandfather->_right;
			//叔叔存在且为红, 往上变色
			if (uncle && uncle->_col == RED)
			{
				parent->_col = uncle->_col = BLACK;
				grandfather->_col = RED;

				//继续往上
				cur = grandfather;
				parent = cur->_parent;
			}
			// 叔叔不存在或者存在且为黑
			else
			{
				if (cur == parent->_left)
				{
					//     g  
					//   p   u
					// c 

					RotateR(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//    g
					// p     u
					//    c
					RotateL(parent);
					RotateR(grandfather);
					//cur去了g的位置  g去了u的位置
					cur->_col = BLACK;
					grandfather->_col = RED;

				}
				//根一定是黑色的
				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 // 叔叔不存在,或者存在且为黑
			{
				//    g
				// u     p
				//          c
				if (cur == parent->_right)
				{
					RotateL(grandfather);
					parent->_col = BLACK;
					grandfather->_col = RED;
				}
				else
				{
					//    g
					// u     p
					//    c
					RotateR(parent);
					RotateL(grandfather);
					cur->_col = BLACK;
					grandfather->_col = RED;
				}

				break;
			}

		}

	}

	// 如果根节点变红了 设回黑
	_root->_col = BLACK;
	return make_pair(Iterator(newnode), true);

}

3.补充成员函数

在简单实现中,我们需要把必要的默认成员函数补上。

//我们手写了默认成员函数后 编译器不在为我们自动生成
	// + default 要编译器给我们生成默认构造 运行效率更好
RBTree() = default;

//拷贝
RBTree(const RBTree<K, T, KeyOfT>& t)
{
	//深拷贝
	_root = _Copy(t._root);
}
//赋值 重载运算符
RBTree<K, T, KeyOfT>& operator=(const RBTree<K, T, KeyOfT> t)
{
	//t是形参 相当于和副本交换了
	swap(_root, t._root);
	return *this;
}

~RBTree()
{
	_Distory(_root);
	_root = nullptr;
}

private:

	//递归式删除
	void _Distory(Node* root)
	{
		if (root == nullptr)
			return;

		_Distory(root->_left);
		_Distory(root->_right);

		delete root;
		root = nullptr;
	}

	Node* _Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		Node* newroot = new Node(root->_data);
		newroot->_col = root->_col;

		newroot->_left = _Copy(root->_left);
		if (newroot->_left)
			newroot->_left->_parent = newroot;

		newroot->_right = _Copy(root->_right);
		if (newroot->_right)
			newroot->_right->_parent = newroot;

		return newroot;
	}

三.封装set与map

1.迭代器的实现

对于迭代器,我们要实现begin()、end()、*iterator、iterator->、++iterator、!=这四种常见功能。另外,我们希望从外部访问迭代器,只访问到树节点的数据:set只访问K,map只访问pair<const K, V>,因为用户访问树节点的左右父亲颜色等没有意义。

初始化:用一个树的节点来初始化

begin()与end():

对于一棵红黑树,其中序遍历时有序的,也就是说我们在用迭代器从begin()访问到end()的过程中也是有序的基于此,迭代器的begin()指向的位置应当是整棵树中最小的数即最左的节点(图中改为1)。end()作为最大节点的后一个元素,为空即可。

*iterator:对迭代器解引用,应返回对数据的引用

iterator->:引出迭代器的元素,应返回对应数据的地址(编译器会帮我们优化)

++iterator:对于前置++操作,在上图中访问顺序为1-6-8-11-13-15-17-22-25-27

规律为:若一个节点有右子树,则访问其右子树的最左节点;若没有右子树,则倒着往上寻找一个孩子为父亲左的一个祖先。

!=:直接比较两个值相不相等即可。

在树外新建一个类进行实现,当然也可以嵌在树中当内部类。

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

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

	// 迭代器常见操作

	//返回引用
	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}
	
	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
	//前置++
	Self& operator++()
	{
		//++操作迭代器指向的元素一定是按顺序的
		if (_node->_right)
		{
			//如果有右树, 下一个节点为右数的最左边
			Node* leftMin = _node->_right;
			while (leftMin->_left)
			{
				leftMin = leftMin->_left;
			}
			_node = leftMin;
		}
		else
		{
		    //没有右树,倒着在祖先里找,找孩子是父亲左的祖先
			Node* cur = _node;
			Node* parent = cur->_parent;

			while (parent && cur == parent->_right)
			{
				cur = parent;
				parent = cur->_parent;
			}

			_node = parent;
		}
		return *this;
	}

};



Iterator Begin()
{
	//空不空无所谓
	Node* leftMin = _root;
	while (leftMin && leftMin->_left)
	{
		leftMin = leftMin->_left;
	}
	return Iterator(leftMin);
}


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

2.函数接口

在我们map与set里面对迭代器的接口封装以下即可。

set:

template<class K>
class set
{
	//仿函数  因为map中红黑树的T 为pair, set中为K, 为了泛型编程
	//我们使用仿函数对map和set进行统一处理
	struct SetKeyOfT
	{
		const K& operator()(const K& key)
		{
			return key;
		}
	};
public:

	//消除二义性 让编译器知道你要给一个类型取别名 而不是 定义一个变量
	typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;

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

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

private:

	RBTree<K, const K, SetKeyOfT> _t;
};

map:

template<class K, class V>
class map
{
	//仿函数  因为map中红黑树的T 为pair, set中为K, 为了泛型编程
	//我们使用仿函数对map和set进行统一处理
	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;	
	                
    iterator begin()
	{
		return _t.Begin();
	}

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

private:
	// key不能修改(第一个k为什么不加const?
	//第一个K 只用于删除和查找, 外层修改不到。
	RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};

3.map中的operator[]

对于map,其支持方括号下标访问。

形如:

map<string, int> mp;

mp[”x”] = 1;

其原理为若有”x“,则修改其对应值为1,若无“x”,则插入”x“,值为1。

所以重载[]时应进行插入,用pair类型接收。

V& operator[](const K& key)
{
	pair<iterator, bool> ret = _t.Insert({key,V()});
	//map迭代器是一个节点的指针 "->"我们重载过 得到pair类型 pair<const K, V> 返回second;
	return ret.first->second;
}

四.完整代码

最后补充const迭代器以及一些细节,代码里有注释。附测试。

set.h

#pragma once

//template <class Key, class Compare = less<Key>, class Alloc = alloc>
//class set {
//public:
//    typedef Key key_type;
//    typedef Key value_type;
//private:
//    typedef rb_tree<key_type, value_type,
//        identity<value_type>, key_compare, Alloc> rep_type;
//    rep_type t;  // red-black tree representing set
//}

// 抓重点
// 化繁为简,只关注跟抓重点部分有关系的,其他通通不关注

namespace Xiang
{
	template<class K>
	class set
	{
		//仿函数  因为map中红黑树的T 为pair, set中为K, 为了泛型编程
		//我们使用仿函数对map和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);
		}

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

	private:
		
		RBTree<K, const K, SetKeyOfT> _t;
	};

	void PrintSet(const set<int>& s)
	{
		for (auto e : s)
		{
			cout << e << endl;
		}
	}

	void test_set()
	{
		set<int> s;
		s.insert(4);
		s.insert(2);
		s.insert(5);
		s.insert(15);
		s.insert(7);
		s.insert(1);
		s.insert(5);
		s.insert(7);

		PrintSet(s);

		set<int>::iterator it = s.begin();
		while (it != s.end())
		{
			//*it += 5;

			cout << *it << " ";
			++it;
		}
		cout << endl;

		for (auto e : s)
		{
			cout << e << " ";
		}
		cout << endl;

		set<int> copy = s;
		for (auto e : copy)
		{
			cout << e << " ";
		}
		cout << endl;
		//cout << copy._t.IsBalance() << endl;
	}
}

map.h

#pragma once
//template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
//class map {
//public:
//    typedef Key key_type;
//    typedef pair<const Key, T> value_type;
//
//private:
//    typedef rb_tree<key_type, value_type,
//        select1st<value_type>, key_compare, Alloc> rep_type;
//    rep_type t;  // red-black tree representing map
//};


namespace Xiang
{
	template<class K, class V>
	class map
	{
		//仿函数  因为map中红黑树的T 为pair, set中为K, 为了泛型编程
		//我们使用仿函数对map和set进行统一处理
		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);
		}
		//find 返回迭代器
		iterator find(const K& key)
		{
			return _t.Find(key);
		}

		V& operator[](const K& key)
		{
			pair<iterator, bool> ret = _t.Insert({key,V()});
			//map迭代器是一个节点的指针 "->"我们重载过 得到pair类型 pair<const K, V> 返回second;
			return ret.first->second;
		}


	private:
		// key不能修改(第一个k为什么不加const?
		//第一个K 只用于删除和查找, 外层修改不到。
		RBTree<K, pair<const K, V>, MapKeyOfT> _t;
	};

	void test_map1()
	{
		map<string, int> m;
		m.insert({ "乐",1 });
		m.insert({ "通",1 });
		m.insert({ "给",1 });
		m.insert({ "哦",3 });

		cout << m["乐"] << endl << "有乐" << endl;
		map<string, int>::iterator it = m.begin();
		while (it != m.end())
		{
			//it->first += 'x';
			it->second += 1;

			//cout << it.operator->()->first << ":" << it->second << endl;
			cout << it->first << ":" << it->second << endl;
			++it;
		}
		cout << endl;
	}

	void test_map2()
	{
		string arr[] = { "a", "", "a", "", "d", "c", "","他怕", "李", "好", "哦","给","888", "达瓦","h" };
		map<string, int> countMap;
		for (auto& e : arr)
		{
			countMap[e]++;
		}

		for (auto& kv : countMap)
		{
			cout << kv.first << ":" << kv.second << endl;
		}
		cout << endl;
	}
}

RBTree.h

#pragma once

enum Colour
{
	RED,   //0
	BLACK  //1
};

//RBTree树节点
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 __RBTreeIterator
{
	typedef RBTreeNode<T> Node;
	typedef __RBTreeIterator<T, Ref, Ptr> Self;
	Node* _node;

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

	// 迭代器常见操作

	//返回引用
	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}
	
	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
	//前置++
	Self& operator++()
	{
		//++操作迭代器指向的元素一定是按顺序的
		if (_node->_right)
		{
			//如果有右树, 下一个节点为右数的最左边
			Node* leftMin = _node->_right;
			while (leftMin->_left)
			{
				leftMin = leftMin->_left;
			}
			_node = leftMin;
		}
		else
		{
		    //没有右树,倒着在祖先里找,找孩子是父亲左的祖先
			Node* cur = _node;
			Node* parent = cur->_parent;

			while (parent && cur == parent->_right)
			{
				cur = parent;
				parent = cur->_parent;
			}

			_node = parent;
		}
		return *this;
	}

};


template<class K, class T, class KeyOfT>
class RBTree
{
	typedef RBTreeNode<T> Node;
public:

	typedef __RBTreeIterator<T, T&, T*> Iterator;
	typedef __RBTreeIterator<T, const T&, const T*> ConstIterator;

	//我们手写了默认成员函数后 编译器不在为我们自动生成
	// + default 要编译器给我们生成默认构造 运行效率更好
	RBTree() = default; 

	//拷贝
	RBTree(const RBTree<K, T, KeyOfT>& t)
	{
		//深拷贝
		_root = _Copy(t._root);
	}
	//赋值 重载运算符
	RBTree<K, T, KeyOfT>& operator=(const RBTree<K, T, KeyOfT> t)
	{
		 //t是形参 相当于和副本交换了
		swap(_root, t._root);
		return *this;
	}

	~RBTree()
	{
		_Distory(_root);
		_root = nullptr;
	}

	//begin 为最左节点   end为空节点
	Iterator Begin()
	{
		//空不空无所谓
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)
		{
			leftMin = leftMin->_left;
		}
		return Iterator(leftMin);
	}
	
	ConstIterator Begin() const
	{
		Node* leftMin = _root;
		while (leftMin && leftMin->_left)
		{
			leftMin = leftMin->_left;
		}
		return ConstIterator(leftMin);
	}

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

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

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

		return End();
	}
	//插入成功--->返回插入位置和true
	//插入失败--->返回该元素存在的位置和false
	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)
		{
			// K
			// pair<K, V>
			// kot对象,是用来取T类型的data对象中的key
			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);
		cur->_col = RED;
		//记录cur位置
		Node* newnode = cur;

		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 (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				//叔叔存在且为红, 往上变色
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;

					//继续往上
					cur = grandfather;
					parent = cur->_parent;
				}
				// 叔叔不存在或者存在且为黑
				else
				{
					if (cur == parent->_left)
					{
						//     g  
						//   p   u
						// c 

						RotateR(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						// p     u
						//    c
						RotateL(parent);
						RotateR(grandfather);
						//cur去了g的位置  g去了u的位置
						cur->_col = BLACK;
						grandfather->_col = RED;

					}
					//根一定是黑色的
					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 // 叔叔不存在,或者存在且为黑
				{
					//    g
					// u     p
					//          c
					if (cur == parent->_right)
					{
						RotateL(grandfather);
						parent->_col = BLACK;
						grandfather->_col = RED;
					}
					else
					{
						//    g
						// u     p
						//    c
						RotateR(parent);
						RotateL(grandfather);
						cur->_col = BLACK;
						grandfather->_col = RED;
					}

					break;
				}

			}

		}

		// 如果根节点变红了 设回黑
		_root->_col = BLACK;
		return make_pair(Iterator(newnode), true);

	}

	//右旋
	void RotateR(Node* parent)
	{
		// 要更改六条边
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		// 先处理parent和SubLR
		parent->_left = subLR;
		if (subLR)
			subLR->_parent = parent;

		//再处理parent和 subl
		//因为 后面需要把 parent的parent和subl链接
		//需要先保存parent的parent
		subL->_right = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subL;

		//处理 subl的 父节点
		if (parent == _root)
		{
			_root = subL;
			_root->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}

			subL->_parent = ppNode;
		}

	}
	//左旋
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;
		if (subRL)
			subRL->_parent = parent;

		subR->_left = parent;
		Node* ppNode = parent->_parent;
		parent->_parent = subR;

		if (parent == _root)
		{
			_root = subR;
			_root->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
			subR->_parent = ppNode;
		}
	}


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

	bool IsBalance()
	{
		if (_root->_col == RED)
		{
			return false;
		}

		int refNum = 0;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				++refNum;
			}

			cur = cur->_left;
		}

		return _Check(_root, 0, refNum);
	}

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

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

private:

	//递归式删除
	void _Distory(Node* root)
	{
		if (root == nullptr)
			return;

		_Distory(root->_left);
		_Distory(root->_right);

		delete root;
		root = nullptr;
	}

	Node* _Copy(Node* root)
	{
		if (root == nullptr)
			return nullptr;

		Node* newroot = new Node(root->_data);
		newroot->_col = root->_col;

		newroot->_left = _Copy(root->_left);
		if (newroot->_left)
			newroot->_left->_parent = newroot;

		newroot->_right = _Copy(root->_right);
		if (newroot->_right)
			newroot->_right->_parent = newroot;

		return newroot;
	}


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

	int _Height(Node* root)
	{
		if (root == nullptr)
			return 0;

		return max(_Height(root->_left), _Height(root->_right)) + 1;
	}

	bool _Check(Node* root, int blackNum, const int refNum)
	{
		if (root == nullptr)
		{
			//cout << blackNum << endl;
			if (refNum != blackNum)
			{
				cout << "存在黑色节点的数量不相等的路径" << endl;
				return false;
			}

			return true;
		}

		if (root->_col == RED && root->_parent->_col == RED)
		{
			cout << root->_kv.first << "存在连续的红色节点" << endl;
			return false;
		}

		if (root->_col == BLACK)
		{
			blackNum++;
		}

		return _Check(root->_left, blackNum, refNum)
			&& _Check(root->_right, blackNum, refNum);
	}


	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		_InOrder(root->_left);
		cout << root->_kv.first << ":" << root->_kv.second << endl;
		_InOrder(root->_right);
	}

private:
	Node* _root = nullptr;
};


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值