map和set的底层原理

 map_set的底层实现是一棵平衡二叉搜索树,在此之前先回顾一下啊二叉搜索树

一.二叉搜索树

1.原理

任意一个节点,其左子树的key值永远小于该节点的key值,而右子树的key值永远大于该节点的key值,树中不存在节点key值相等的情况。

2.创建及插入

 a. 树为空,则直接新增节点,赋值给root指针                                                                                 b. 树不空,按二叉搜索树性质查找插入位置,插入新节点                                                               c.若已经有相同的值,则插入失败

#include<iostream>
using namespace std;
template <class K>
struct BSTreeNode
{
	struct BSTreeNode<K>* _left;
	struct BSTreeNode<K>* _right;
	K _key;

	BSTreeNode(const K& key)
		:_key(key)
		,_left(nullptr)
		,_right(nullptr)
	{}
};

template<class K>
class BSTree
{
	typedef BSTreeNode<K> Node;
public:
	//插入
	bool Insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* cur = _root;
		Node* prev = cur;
		while (cur)
		{
			if (key < cur->_key)
			{
				prev = cur;
				cur = cur->_left;
			}
			else if (key > cur->_key)
			{
				prev = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(key);
		if (key<prev->_key)
		{
			prev->_left = cur;
		}
		else
		{
			prev->_right = cur;
		}
		return true;
	}
private:
	Node* _root=nullptr;
};

3.中序遍历

即是对这棵树的排序(由小到大):                                                                                                      因为中序遍历的本质就是先(递归左子树,访问该节点,递归右子树)。既然左子树小于该节点,那么遍历出来的左边都大于该节点,同理右子树都大于该节点,那么右边递归出来特都大于该节点。

//中序遍历
void _InOrder(const Node* root)
{
	if (root == nullptr)
	{
		return;
	}
	_InOrder(root->_left);
	cout << root->_key << " ";
	_InOrder(root->_right);
}
void InOrder()
{
	_InOrder(_root);
	cout << endl;
}

4.删除

  二叉树的删除需要删除且不改变树的结构。往前回顾,这种结构的删除是通过将叶子节点换到该节点再进行操作,所以类比堆,我们以可以通过堆叶子节点的处理来进行删除。

针对情况二,找到左树的最右节点 或者 右树的最左节点进行替换即可

//删除
bool Erase(const K& key)
{
	Node* cur = _root;
	Node* prev = cur;
    //找要删除的节点
	while (cur)
	{
		if (key < cur->_key)
		{
			prev = cur;
			cur = cur->_left;
		}
		else if (key > cur->_key)
		{
			prev = cur;
			cur = cur->_right;
		}
        //找到要删的节点
		else
		{
			//左子树为空
			if (cur->_left == nullptr)
			{
				//为根节点
				if (cur == _root)
				{
					_root = cur->_right;
				}
                //不为根节点
				else
				{
					if (cur == prev->_left)
					{
						prev->_left = cur->_right;
					}
					else
					{
						prev->_right = cur->_right;
					}
				}
				delete cur;
				return true;
			}
            //右子树为空
			else if (cur->_right == nullptr)
			{
                //为根节点
				if (cur == _root)
				{
					_root = cur->_left;
				}
                //不为根节点
				else
				{
					if (cur == prev->_right)
					{
						prev->_right = cur->_left;
					}
					else
					{
						prev->_left = cur->_left;
					}
				}
				delete cur;
				return true;
			}
            //左右子树都不为空
			else
			{
                //右树的最左节点替代要删除的节点
				Node* RightMin = cur->_right;
				Node* PrevRightMin = cur;
                //找到右子树中最大的节点
				while (RightMin->_left)
				{
					PrevRightMin = RightMin;
					RightMin = RightMin->_left;
				}
				//找到替代节点,将替代节点中的值交给待删除节点
				cur->_key = RightMin->_key;
				//转换成删除替代节点
				if (RightMin == PrevRightMin->_left)
				{
					PrevRightMin->_left = RightMin->_right;
				}
                //要删除节点的右节点没有左节点
				else
				{
					PrevRightMin->_right = RightMin->_right;
				}
				delete RightMin;
				return true;
			}
		}
	}
    //没找到要删除的节点
	return false;
}

  

5.缺点

二叉搜索树的主要作用可以用于搜索,这样比顺序搜索效率更高,一般情况下为 O(logN)

二叉搜索树是有许多局限的,因为其不能保证此树的树形结构是否平衡,搜索效率就会降低

eg.

左边的搜索效率就不如右侧的搜索效率。故需要一种新型的结构-平衡二叉搜索树

二.平衡二叉搜索树

1.AVLTree

       该结构由两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年,故称为AVLTree。其保证了二叉树在插入新结点的时候,保持每棵树的两个子树高度差不超过1。且是一个三叉链的结构,三叉链保证其能够进行旋转。

a.原理 

为了方便描述与判断,引入平衡因子(Balance Factor) 概念,每一个节点都有一个平衡因子             (平衡因子 = 左子树高度 - 右子树高度)                                                                                           插入新结点后,当树的平衡因子 >=2||<=-2 时,代表此树已经出现不平衡的情况了。需要进行旋转调整

其插入与二叉搜索树大致相同,因为引入了平衡因子,多出了对平衡因子的改变和对树的旋转操作。

插入时一共有 3 种情况:

情况原因措施
1/-1插入前其父节点没有子树继续向上,直到找到平衡或者不平衡
0插入前其父节点只有一个子树,插入到父节点的空枝上无需往上,已经平衡
2/-2插入前其父节点只有一个子树,插入到唯一子树上无需往上,已经不平衡

#include<iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;

	int _bf;//balance factor 平衡因子

	pair<K, V> _kv;
    AVLTreeNode(const pair<K, V>& kv)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_bf(0)
		,_kv(kv)
	{}

};
template<class K,class V>
class AVLTree
{
	typedef AVLTreeNode<K,V> Node;
public:
	bool Insert(pair<K, V> kv)
	{
		//先插入
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if(kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(kv);
		if (kv.first < parent->_kv.first)
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else 
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		//再判断平衡因子
		while (parent)
		{
            //调整平衡因子
			if (cur == parent->_left)
			{
				++parent->_bf;
			}
			else
			{
				--parent->_bf;
			}
            //判断是否需要旋转
			if (parent->_bf == 0)
			{
				break;
			}
			else if (parent->_bf == -1 || parent->_bf == 1)
			{
				cur = parent;
				parent = parent->_parent;
			}
			else if(parent->_bf == -2 || parent->_bf == 2)
			{
				//出现问题,需要旋转
			}
		}
		return true;
	}

以上代码并没有实现旋转的功能

b.单旋转(直线)

当增加高度的树在同一侧时,可以进行单旋转,即将 “问题节点压下去,sub节点升起来,再对子树进行处理”。                                                                                                                                    这是左单旋转,右单旋转与之类似

定义sub为问题节点的右节点(左单旋情况),问题节点为parent。

//左单旋
void RotateL(Node* parent)
{
	//右孩子
	Node* subR = parent->_right;
	//右孩子的左孩子
	Node* subRL = subR->_left;
	//parent的parent
	Node* ppNode = parent->_parent;
	//右孩子的左边给parent
	parent->_right = subRL;
	if (subRL)
	{
		subRL->_parent = parent;
	}
	//parent给subR的左边
	subR->_left = parent;
	parent->_parent = subR;
	//subR连接上面
	subR->_parent = ppNode;
	//上面连接subR
	if (_root == parent)//问题节点是根节点
	{
		_root = subR;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = subR;
		}
		else
		{
			ppNode->_right = subR;
		}
	}
	parent->_bf = subR->_bf = 0;
}

//右单旋
void RotateR(Node* parent)
{
	//左孩子
	Node* subL= parent->_left;
	//左孩子的右孩子
	Node* subLR = subL->_right;
	//parent的parent
	Node* ppNode = parent->_parent;
	//左孩子的右边给parent
	parent->_left = subLR;
	if (subLR)
	{
		subLR->_parent = parent;
	}
	//parent给subL的右边
	subL->_right = parent;
	parent->_parent = subL;
	//subL连接上面
	subL->_parent = ppNode;
	//上面连接subR
	if (_root == parent)//问题节点是根节点
	{
		_root = subL;
	}
	else
	{
		if (ppNode->_left == parent)
		{
			ppNode->_left = subL;
		}
		else
		{
			ppNode->_right = subL;
		}
	}
	parent->_bf = subL->_bf = 0;
}

旋转完成后无需继续向上迭代,该子树已经回到插入前的高度

c.双旋转(折线)

  当增加高度的树并不在同一侧时,就无法单旋转了,此时需要进行双旋转。

 以左右双旋为例

双旋转会改变平衡因子。所以不单单只是双旋转就结束,还要进行对平衡因子的改变。.

       当subLR的Bf是-1时,subL是1,parent是 0;
  当subLR的Bf是 1时,subL是0,parent是-1;
  当subLR的Bf是 0时,subL是0,parent是 0;

void RotateRL(Node* parent)
{
	Node* subR = parent->_right;
	Node* subRL = subR->_left;
	int bf = subRL->_bf;
	RotateR(subR);
	RotateL(parent);
	if (bf == 1)
	{
		parent->_bf = 0;
		subR->_bf = -1;
		subRL->_bf = 0;
	}
	else if (bf == -1)
	{
		parent->_bf = 1;
		subR->_bf = 0;
		subRL->_bf = 0;
	}
	else if (bf == 0)
	{
		parent->_bf = 0;
		subR->_bf = 0;
		subRL->_bf = 0;
	}
}

void RotateLR(Node* parent)
{
	Node* subL = parent->_left;
	Node* subLR = subL->_right;
	int bf = subLR->_bf;
	RotateL(subL);
	RotateR(parent);
	if (bf == 1)
	{
		parent->_bf = -1;
		subL->_bf = 0;
		subLR->_bf = 0;
	}
	else if (bf == -1)
	{
		parent->_bf = 0;
		subL->_bf = 1;
		subLR->_bf = 0;
	}
	else if (bf == 0)
	{
		parent->_bf = 0;
		subL->_bf = 0;
		subLR->_bf = 0;
	}
}

旋转完成后无需继续向上迭代,该子树已经回到插入前的高度

d.旋转总结

假如以Parent为根的子树不平衡,即Parent的平衡因子为2或者-2,分以下情况考虑
 1. Parent的平衡因子为-2,说明Parent的右子树高,设Parent的右子树的根为SubR
     当SubR的平衡因子为-1时,执行左单旋
     当SubR的平衡因子为1时,执行右左双旋
2. Parent的平衡因子为2,说明Parent的左子树高,设Parent的左子树的根为SubL
    当SubL的平衡因子为1是,执行右单旋
    当SubL的平衡因子为-1时,执行左右双旋
旋转完成后,原Parent为根的子树个高度降低,已经平衡,不需要再向上更新。

e.完整代码

#include<iostream>
using namespace std;
template<class K,class V>
struct AVLTreeNode
{
	AVLTreeNode<K, V>* _left;
	AVLTreeNode<K, V>* _right;
	AVLTreeNode<K, V>* _parent;

	int _bf;//balance factor 平衡因子

	pair<K, V> _kv;
    AVLTreeNode(const pair<K, V>& kv)
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_bf(0)
		,_kv(kv)
	{}

};

template<class K,class V>
class AVLTree
{
	typedef AVLTreeNode<K,V> Node;
public:
	bool Insert(pair<K, V> kv)
	{
		//先插入
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if(kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(kv);
		if (kv.first < parent->_kv.first)
		{
			parent->_left = cur;
			cur->_parent = parent;
		}
		else 
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		//再判断
		while (parent)
		{
			if (cur == parent->_left)
			{
				++parent->_bf;
			}
			else
			{
				--parent->_bf;
			}
			if (parent->_bf == 0)
			{
				break;
			}
			else if (parent->_bf == -1 || parent->_bf == 1)
			{
				cur = parent;
				parent = parent->_parent;
			}
			else if(parent->_bf == -2 || parent->_bf == 2)
			{
				//出现问题,需要旋转
				if (parent->_bf == 2)
				{
					if (cur->_bf == 1)
					{
						RotateR(parent);
					}
					else if(cur->_bf==-1)
					{
						RotateLR(parent);
					}
				}
				else if (parent->_bf == -2)
				{
					if (cur->_bf == -1)
					{
						RotateL(parent);
					}
					else if(cur->_bf == 1)
					{
						RotateRL(parent);
					}
				}
				break;
			}
		}
		return true;
	}
	//左单旋
	void RotateL(Node* parent)
	{
		//右孩子
		Node* subR = parent->_right;
		//右孩子的左孩子
		Node* subRL = subR->_left;
		//parent的parent
		Node* ppNode = parent->_parent;
		//右孩子的左边给parent
		parent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = parent;
		}
		//parent给subR的左边
		subR->_left = parent;
		parent->_parent = subR;
		//subR连接上面
		subR->_parent = ppNode;
		//上面连接subR
		if (_root == parent)
		{
			_root = subR;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}
		}
		parent->_bf = subR->_bf = 0;
	}
	//右单旋
	void RotateR(Node* parent)
	{
		//左孩子
		Node* subL= parent->_left;
		//左孩子的右孩子
		Node* subLR = subL->_right;
		//parent的parent
		Node* ppNode = parent->_parent;
		//左孩子的右边给parent
		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}
		//parent给subL的右边
		subL->_right = parent;
		parent->_parent = subL;
		//subL连接上面
		subL->_parent = ppNode;
		//上面连接subR
		if (_root == parent)
		{
			_root = subL;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
		}
		parent->_bf = subL->_bf = 0;
	}
	void RotateRL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;
		int bf = subRL->_bf;
		RotateR(subR);
		RotateL(parent);
		if (bf == 1)
		{
			parent->_bf = 0;
			subR->_bf = -1;
			subRL->_bf = 0;
		}
		else if (bf == -1)
		{
			parent->_bf = 1;
			subR->_bf = 0;
			subRL->_bf = 0;
		}
		else if (bf == 0)
		{
			parent->_bf = 0;
			subR->_bf = 0;
			subRL->_bf = 0;
		}
	}
	void RotateLR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;
		int bf = subLR->_bf;
		RotateL(subL);
		RotateR(parent);
		if (bf == 1)
		{
			parent->_bf = -1;
			subL->_bf = 0;
			subLR->_bf = 0;
		}
		else if (bf == -1)
		{
			parent->_bf = 0;
			subL->_bf = 1;
			subLR->_bf = 0;
		}
		else if (bf == 0)
		{
			parent->_bf = 0;
			subL->_bf = 0;
			subLR->_bf = 0;
		}
	}
	//中序遍历
	void _InOrder(const Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_InOrder(root->_left);
		cout << root->_kv.first << ":" << root->_kv.second << endl;
		_InOrder(root->_right);
	}
	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}
	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 Height()
	{
		return _Height(_root);
	}
private:
	Node* _root = nullptr;
};

AVLTree 的 一大优点就是其搜索效率极高达到 O(logn) ,但美中不足的是,他的插入效率并不高效,每一次插入都需要严格的遵守AVLTree的平衡原则。故出现了一种更高效的树形结构——红黑树。

2.RBTree(红黑树)

红黑树区别于AVLTree的一个关键点,就是其对于平衡条件不再过于苛刻了,其最终目的是:
  最长路径不超过最短路径的两倍

其要求为:
1.根节点必须是黑色。
2.叶子节点是黑色。(此处的叶子结点指的是空结点)
3.红色节点的子节点是黑色。
4.任意节点到其叶节点的任一路径上,黑色节点数量相同。                                                           维护好以上关系,则此红黑树的最长路径永远也不会超过最短路径的两倍,
 因为最短路径为全黑,最长路径为红黑交替,但黑色节点的个数不变,所以一定小于二倍。

a.插入

在插入的时候,我们通常将节点的初始颜色设定为红色,因为红节点相邻这条规则比黑节点在所有路径上的个数相同这条规则更好维护。

插入的3种状况:                                                                                                                                  1.正常插入,插入节点的parent为黑色
  2.插入时,插入节点的parent为红色,且uncle为红色

  3.插入时,插入节点的parent为红色,但uncle为黑色或不存在(因为uncle为黑色,所以不能贸然修改节点颜色)                                                                                                                                        注意:下面两种情况都不是插入节点后直接产生,而是情况2转化而来(不然从一个节点出发到空节点的路径上,黑色节点数目不同)                                                                                                            3.1 cur与parent呈直线型(单旋转)
请添加图片描述

  3.2 cur与parent呈折线型(双旋转)

请添加图片描述

(上图到下图,cur和p所指的节点值未交换,为了方便只是将名称互换)
在这里插入图片描述

#include<iostream>
using namespace std;
enum Color
{
	BLACK,
	RED
};

template<class K,class V>
struct RBTreeNode
{
	RBTreeNode(const pair<K,V>& kv)
		:_parent(nullptr)
		, _right(nullptr)
		, _left(nullptr)
		, _col(BLACK)
	    ,_kv(kv)
	{}
	RBTreeNode<K,V>* _parent;
	RBTreeNode<K,V>* _right;
	RBTreeNode<K,V>* _left;
	pair<K, V> _kv;
	Color _col;
};


template<class K,class V>
class RBTree
{
	typedef RBTreeNode<K,V> Node;
public:
	//先插入
	bool Insert(const pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = BLACK;
			return true;
		}
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(kv);
		if (cur->_kv.first < parent->_kv.first)
		{
			cur->_parent = parent;
			parent->_left = cur;
		}

		else
		{
			cur->_parent = parent;
			parent->_right = cur;
		}
		cur->_col = RED;
        //判断颜色
		while (parent && parent->_col == RED)
		{
			//红黑树的关键看uncle
			//parent为红,则不为根,则grandfather存在且为黑
			Node* grandfather = parent->_parent;
			//如果parent在grandfather的左边
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				//uncle存在且为红,不旋转,只变色
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				//uncle不存在或为黑,旋转为直线,再变色
				else
				{
					//是曲线,先左旋
					if (cur == parent->_right)
					{
						RotateL(parent);
						swap(parent, cur);
					}
					//已经是直线
					RotateR(grandfather);
					//变色,顶上的节点变为黑就不用继续向上循环了
					parent->_col = BLACK;
					grandfather->_col = RED;
					break;
				}
			}
			//如果parent在grandfather的右边
			else
			{
				//uncle在左
				Node* uncle = grandfather->_left;
				//uncle存在且为红
				if (uncle && uncle->_col == RED)
				{
					grandfather->_col = RED;
					parent->_col = uncle->_col = BLACK;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{
						RotateR(parent);
						swap(cur, parent);
					}
					RotateL(grandfather);
					//变色
					parent->_col = BLACK;
					grandfather->_col = RED;
					break;
				}
			}
		}
		_root->_col = BLACK;
		return true;
	}

    //左单旋
	void RotateL(Node* parent)
	{
		//右孩子
		Node* subR = parent->_right;
		//右孩子的左孩子
		Node* subRL = subR->_left;
		//parent的parent
		Node* ppNode = parent->_parent;
		//右孩子的左边给parent
		parent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = parent;
		}
		//parent给subR的左边
		subR->_left = parent;
		parent->_parent = subR;
		//subR连接上面
		subR->_parent = ppNode;
		//上面连接subR
		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;
		//parent的parent
		Node* ppNode = parent->_parent;
		//左孩子的右边给parent
		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}
		//parent给subL的右边
		subL->_right = parent;
		parent->_parent = subL;
		//subL连接上面
		subL->_parent = ppNode;
		//上面连接subR
		if (_root == parent)
		{
			_root = subL;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}
		}
	}
private:
	Node* _root = nullptr;
};

3.红黑树与AVL树的比较

       红黑树和AVL树都是高效的平衡二叉树,增删改查的时间复杂度都是O(log2 N),红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。

三.模拟实现map和set

在STL源码之中,map和set的底层都是红黑树

1.改造红黑树

a.仿函数

set中数据样式为key,map中数据样式为pair<key,value>,而实现查找,删除等功能时需要key值

为了代码复用这里用到仿函数和另一种对键值对的处理方式。
  好比,RBTree< K, V , FUNC >                                                                                                其中K是键,V是值,FUNC是从V中提炼K的仿函数。
这样在map中红黑树为,RBTree<K,pair<K,V>,Func>
在set中红黑树为,RBTree<K, K , Func>

b.迭代器

此迭代器的本质其实是:

操作本质实现
operator++找到下一个比它大的最小元素右子树的最左节点(后继节点)
operator–找到上一个比它小的最大元素左子树的最右节点(前驱节点)
//迭代器
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 &_node->_data;
	}
	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 && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
			
		}
		return *this;
	}
	Self& operator--()
	{
		//左边不为空
		if (_node->_left)
		{
			Node* subRight = _node->_left;
			while (subRight->_right)
			{
				subRight = subRight->_right;
			}
			_node = subRight;
		}
		//左为空
		else
		{
			Node* cur = _node;
			Node* parent = _node->_parent;
			while (parent && cur == parent->_left)
			{
				cur = parent;
				parent = parent->parent;
			}
			_node = parent;
		}
		return *this;
	}
	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
	Ptr operator->()
	{
		return &_node->_data;
	}
};

c.代码

enum Color
{
	BLACK,
	RED
};

template<class T>
struct RBTreeNode
{
	RBTreeNode(const T& data)
		:_parent(nullptr)
		, _right(nullptr)
		, _left(nullptr)
		, _col(BLACK)
		, _data(data)
	{}
	RBTreeNode<T>* _parent;
	RBTreeNode<T>* _right;
	RBTreeNode<T>* _left;
	T _data;
	Color _col;
};
//迭代器
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 &_node->_data;
	}
	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 && cur == parent->_right)
			{
				cur = cur->_parent;
				parent = parent->_parent;
			}
			_node = parent;
			
		}
		return *this;
	}
	Self& operator--()
	{
		//左边不为空
		if (_node->_left)
		{
			Node* subRight = _node->_left;
			while (subRight->_right)
			{
				subRight = subRight->_right;
			}
			_node = subRight;
		}
		//左为空
		else
		{
			Node* cur = _node;
			Node* parent = _node->_parent;
			while (parent && cur == parent->_left)
			{
				cur = parent;
				parent = parent->parent;
			}
			_node = parent;
		}
		return *this;
	}
	bool operator!=(const Self& s)
	{
		return _node != s._node;
	}
	bool operator==(const Self& s)
	{
		return _node == s._node;
	}
	Ptr operator->()
	{
		return &_node->_data;
	}
};

template<class K, class T,class KOfT>
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;
		while (cur && cur->_left)
		{
			cur = cur->_left;
		}
		return iterator(cur);
	}
	iterator end()
	{
		return iterator(nullptr);
	}
	//左单旋
	void RotateL(Node* parent)
	{
		//右孩子
		Node* subR = parent->_right;
		//右孩子的左孩子
		Node* subRL = subR->_left;
		//parent的parent
		Node* ppNode = parent->_parent;
		//右孩子的左边给parent
		parent->_right = subRL;
		if (subRL)
		{
			subRL->_parent = parent;
		}
		//parent给subR的左边
		subR->_left = parent;
		parent->_parent = subR;
		//subR连接上面
		subR->_parent = ppNode;
		//上面连接subR
		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;
		//parent的parent
		Node* ppNode = parent->_parent;
		//左孩子的右边给parent
		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}
		//parent给subL的右边
		subL->_right = parent;
		parent->_parent = subL;
		//subL连接上面
		subL->_parent = ppNode;
		//上面连接subR
		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);
		}
		KOfT koft;
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (koft(data) < koft(cur->_data))
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (koft(data) > koft(cur->_data))
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return make_pair(iterator(cur),false);
			}
		}
		cur = new Node(data);
		//当前cur指向新增节点
		Node* newnode = cur;
		if (koft(cur->_data) < koft(parent->_data))
		{
			cur->_parent = parent;
			parent->_left = cur;
		}

		else
		{
			cur->_parent = parent;
			parent->_right = cur;
		}
		cur->_col = RED;
		while (parent && parent->_col == RED)
		{
			//红黑树的关键看uncle
			//parent为红,则不为根,则grandfather存在且为黑
			Node* grandfather = parent->_parent;
			//如果parent在grandfather的左边
			if (parent == grandfather->_left)
			{
				Node* uncle = grandfather->_right;
				//uncle存在且为红,不旋转,只变色
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandfather->_col = RED;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				//uncle不存在或为黑,旋转为直线,再变色
				else
				{
					//是曲线,先左旋
					if (cur == parent->_right)
					{
						RotateL(parent);
						swap(parent, cur);
					}
					//已经是直线
					RotateR(grandfather);
					//变色,顶上的节点变为黑就不用继续向上循环了
					parent->_col = BLACK;
					grandfather->_col = RED;
					break;
				}
			}
			//如果parent在grandfather的右边
			else
			{
				//uncle在左
				Node* uncle = grandfather->_left;
				//uncle存在且为红
				if (uncle && uncle->_col == RED)
				{
					grandfather->_col = RED;
					parent->_col = uncle->_col = BLACK;
					//继续向上处理
					cur = grandfather;
					parent = cur->_parent;
				}
				else
				{
					if (cur == parent->_left)
					{
						RotateR(parent);
						swap(cur, parent);
					}
					RotateL(grandfather);
					//变色
					parent->_col = BLACK;
					grandfather->_col = RED;
					break;
				}
			}
		}
		_root->_col = BLACK;
		return make_pair(iterator(newnode),true);
	}

	//查找
	iterator Find(const K& k)
	{
		KOfT koft;
		Node* cur = _root;
		while (cur)
		{
			if (k < koft(cur->_data))
			{
				cur = cur->_left;
			}
			else if (k > koft(cur->_data))
			{
				cur = cur->_right;
			}
			else
			{
				return iterator(cur);
			}
		}
		return iterator(nullptr);

	}

	
private:
	Node* _root = nullptr;
};

2.set实现

template<class K>
class set
{
public:
	
	struct SetKeyOfT
	{
		const K& operator()(const K& k)
		{
			return k;
		}
	};
	//让编译器知道这个嵌套从属名称是一个类型名
	typedef  typename RBTree<K, K, SetKeyOfT>::iterator iterator;
	iterator begin()
	{
		return _t.begin();
	}
	iterator end()
	{
		return _t.end();
	}
	pair<iterator, bool> Insert(const K& k)
	{
		return _t.Insert(k);
	}
private:
	RBTree<K, K, SetKeyOfT> _t;
};

3.map实现

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

	typedef  typename RBTree<K, pair<K,V>, MapKeyOfT>::iterator iterator;
	iterator begin()
	{
		return _t.begin();
	}
	iterator end()
	{
		return _t.end();
	}
	pair<iterator,bool> Insert(const pair<K, V>& kv)
	{
		return _t.Insert(kv);
	}
	V& operator[](const K& k)
	{
		pair<iterator, bool> p = _t.Insert(make_pair(k, V()));
		return p.first->second;
	}
private:
	RBTree<K, pair<K, V>, MapKeyOfT> _t;
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值