左倾红黑树插入结果可视化:

插入顺序:6 7 1 5 3 4 2

put:6

put:7

put:1

put:5

put:3

put:4

put:2

#include <iostream>
#include <cstdlib>
#include <ctime>

template<class _Key, class _Value>
class LLRBT
{
	enum color_t { BLACK, RED };
	
	struct Node 
	{
		_Key		key;	
		_Value 		value;
		
		size_t 		count; //此节点所有孩子节点数+1 
		color_t		color; //指向本节点的链接颜色 
		
		struct Node *left, 
					*right;
		
		Node(	const _Key & 	pKey, 
				const _Value & 	pValue, 
				color_t 		pColor	= RED,	
				size_t 			pCount	= 1,		
				struct Node *	pLeft	= nullptr, 	 
				struct Node *	pRight	= nullptr)
				
			: key(pKey), value(pValue), count(pCount), color(pColor), left(pLeft), right(pRight) {	}
					
	};
	
	
	//定义根节点 
	Node * root_ = nullptr; 

	void clear(Node * node)
	{
		if(node == nullptr) return;

		clear(node->left);
		clear(node->right);
		
		delete node;
	}
	
	//判断一个节点是否为红节点(即链接到此节点的链接颜色为红色) 
	bool is_red(Node * node) const
	{
		return (node) ? (node->color == RED) : false;
	}
	
	//取节点的所有孩子节点及其自身的节点数 
	size_t size(Node * node) const
	{
		return (node) ? (node->count) : 0;
	}
	
	//判断红黑树中是否存在指定的节点
	bool contains(Node * node, const _Key & key)
	{
		while(node)
		{
			if		(key < node->key) 	node = node->left;
			else if	(node->key < key)	node = node->right;
			else						return true;
		}
		return false;
	}

	//取最小节点 
	Node * min(Node * node)
	{
		while(node && node->left) node = node->left;
		return node;
	}
	
	
	//左旋转节点的右链接 
	Node * rotate_left(Node * node)
	{
		Node * p 	= node->right;
		
		node->right = p->left;
		p	->left 	= node;
		
		p	->color	= node->color; 
		node->color = RED;
		
		//更新节点数量统计 
		p	->count	= node->count;
		node->count	= size(node->left) + size(node->right) + 1;
		
		return p;
	}
	
	//右旋转节点的左链接 
	Node * rotate_right(Node * node)
	{
		Node * p	= node->left;
		
		node->left	= p->right;
		p	->right	= node;
		
		p	->color = node->color;
		node->color	= RED;
		
		//更新节点数量统计 
		p	->count	= node->count;
		node->count = size(node->left) + size(node->right) + 1;
		
		return p;
	}
	
	//节点颜色转换(分解4-节点或向父节点'借'节点操作) 
	void flip_colors(Node * node)
	{
		node->color			= (node->color == RED) 			? BLACK : RED;
		node->left->color	= (node->left->color == RED) 	? BLACK : RED;
		node->right->color	= (node->right->color == RED) 	? BLACK : RED;
	}
	
	//插入新的节点 
	Node * put(Node * parent, const _Key & key, const _Value & value)
	{
		if(!parent) return new Node(key, value, RED);
		
		if		(key < parent->key) parent->left  = put(parent->left, key, value);
		else if	(parent->key < key) parent->right = put(parent->right, key, value);
		else						parent->value = value;
		
		/*左节点连接是黑色,右节点连接是红色,则左转节点
		左倾红黑树不允许红色链接出现在右边,若有红色链接出现在右边就进行左旋转操作 
		
		('..'代表红色节点,'.'代表黑色节点)
		    3				5
		      ..	=>	  ..
		       ..		 ..
		         5		3
		*/ 
		if(!is_red(parent->left) && is_red(parent->right))		parent = rotate_left(parent);
		
		/*
		节点连接连续红色,右转节点 
		      5
		     ..				3
		    ..			   ...
		   3		=>	  .. ..
		  ..			  1   5
		 ..
		 1
		*/
		if(is_red(parent->left) && is_red(parent->left->left))	parent = rotate_right(parent);
		
		
		/*
		左右连接全为红色,则将左右连接设置为红色,其父节点设为红色 
		   3			  3
		  ...		=>	 . .
		 ..  ..         .   .
		 1    5         1   5 
		*/ 
		if(is_red(parent->left) && is_red(parent->right))		flip_colors(parent);
		
		//更新节点数量统计 
		parent->count = size(parent->left) + size(parent->right) + 1;
		
		return parent;
	}
	
	//恢复左倾红黑树的平衡性 
	Node * balance(Node * node)
	{
		//'借孩子'操作可能导致红色节点出现在右边,这在左倾红黑树中是不可以出现的,需要左旋转进行修复 
		if(is_red(node->right)) 							node = rotate_left(node);
		//左节点连接是黑色,右节点连接是红色,则左转节点 
		if(!is_red(node->left) && is_red(node->right))		node = rotate_left(node);
		//左节点连接连续红色,右转节点 
		//is_red(node->left)若为红色节点则node->left必定存在
		//所以此处is_red(node->left->left)是安全的
		if(is_red(node->left) && is_red(node->left->left))	node = rotate_right(node);
		//左右连接全为红色,则将左右连接设置为红色,其父节点设为红色 
		if(is_red(node->left) && is_red(node->right))		flip_colors(node);
		
		node->count = size(node->left) + size(node->right) + 1;
		
		return node;
	}

	//借一个红色节点给左孩子 
	Node * move_red_left(Node * node)
	{
		//首先向父节点借一个节点 
		flip_colors(node);
		
		if(is_red(node->right->left))
		{
			//它的亲兄弟节点不是2-节点,从其亲兄弟借一个节点到左节点中
			node->right = rotate_right(node->right);
			node = rotate_left(node);
		}
		
		return node;
	}
	
	//移除最小的节点 
	Node * remove_min(Node * node)
	{
		if(node->left == nullptr)
		{
			delete node;
			return nullptr;
		}
		
		/* 关于删除最小节点的规则
		确保当前节点不是2-节点
		1.如果当前节点的左节点不是2-节点,则继续
		2.如果当前节点的左节点是-2节点,且它的亲兄弟节点不是2-节点,则从其亲兄弟借一个节点到左节点中
		3.如果当前节点的左节点是-2,且它的亲兄弟也是2-节点,则将父节点中的最小键及其兄弟节点合并为一个4-节点 */
		if(!is_red(node->left) && !is_red(node->left->left))
		{
			//非2-节点,父亲或亲兄弟节点借一个节点给左节点,以确保左节点不是2-节点
			node = move_red_left(node);
		}

		node->left = remove_min(node->left);
		
		//删除操作完成后需要由下至上分解所有4-节点
		return balance(node);
	} 
	
	//借一个节点给右孩子 
	Node * move_red_right(Node * node)
	{
		//同move_red_left的注释
		flip_colors(node);
		
		if(is_red(node->left->left))
		{
			node = rotate_right(node);
		}
		
		return node;
	}
	
	//移除最大的节点 
	Node * remove_max(Node * node)
	{
		/* 此处相较于删除最小节点多了一个步骤
		若左孩子为红节点则进行右旋操作,让右节点成为红节点以便接下来的删除操作 
		根据左倾树的性质 若左孩子非红色节点,则必然存在有右子节点

		假设此处不进行右旋,则下列例子的平衡将遭到破坏
		    2
		  ..	由于2节点的右孩子为空,所以2节点是最大节点,此时C1.0处的代码将直接
		 ..		删除2节点,其左节点也被被抛弃
		1

		*/
		if(is_red(node->left)) node = rotate_right(node);
		
		//C1.0
		if(node->right == nullptr)
		{
			delete node;
			return nullptr;
		}
		
		if(!is_red(node->right) && !is_red(node->right->left))
		{
			node = move_red_right(node);
		}
		
		node->right = remove_max(node->right);
		
		//删除操作完成后需要由下至上进行恢复
		return balance(node);
	} 
	
	//将移除最小的节点和移除最大的节点实现结合在一起,即可实现删除任意节点 
	Node * remove(Node * node, const _Key & key)
	{
		if(key < node->key)
		{
			//和删除最小节点时的操作类似,判断节点的左孩子是否为2-节点,若非2-节点则需要借一个红色节点给左孩子
			if(!is_red(node->left) && !is_red(node->left->left))
			{
				node = move_red_left(node);
			}
			node->left = remove(node->left, key);
		}
		else
		{
			if(is_red(node->left)) node = rotate_right(node);
			
			if(node->key == key && (node->right == nullptr))
			{
				delete node;
				return nullptr;
			}
			
			//和删除最大节点的操作类似
			if(!is_red(node->right) && !is_red(node->right->left))
			{
				node = move_red_right(node);
			}
			
			if(node->key == key)
			{
				//找到node的后继节点
				Node * minNode = min(node->right);

				//将后继节点的key-value移动给node
				node->key 	= std::move(minNode->key);
				node->value = std::move(minNode->value);
				
				//删除最小节点无需使用节点的key/value数据,只会不断向左直到最小的那个节点 				
				node->right = remove_min(node->right);
			}
			else
			{
				node->right = remove(node->right, key);
			}
		}
		
		//删除操作完成后需要由下至上进行恢复
		return balance(node);
	}
	
	void print(Node * node) const
	{
		if(node == nullptr) return;
		 
		std::cout << ((node->color == RED) ? 'R' : 'B') << '(' << (node->key) << ')' << ' '; 
		print(node->left);
		print(node->right);
		
		std::cout << "BACK "; 
	}
	
public:

	LLRBT() = default;

	LLRBT(const LLRBT & rhs) = delete;
	LLRBT(const LLRBT && rhs) = delete;

	LLRBT & operator=(const LLRBT & rhs) = delete;
	LLRBT & operator=(const LLRBT && rhs) = delete;

	~LLRBT()
	{
		clear(root_);
	}

	void clear()
	{
		clear(root_);
		root_ = nullptr;
	}

	size_t size() const
	{
		return root_ ? size(root_) : 0;
	}
	
	void put(const _Key & key, const _Value & value)
	{
		root_ = put(root_, key, value);
		root_->color = BLACK; 
	}
	
	_Value * get(const _Key & key) const
	{
		for(Node * node = root_; node != nullptr; )
		{
			if		(node->key < key)	node = node->right;
			else if	(key < node->key)	node = node->left;
			else						return &(node->value);
		}
		
		return nullptr;
	}
	
	void remove_min()
	{
		if(root_ == nullptr) return;
		
		if(!is_red(root_->left) && !is_red(root_->right))
		{
			root_->color = RED;
		}
		
		root_ = remove_min(root_);
		
		if(root_) root_->color = BLACK; 
	}
	
	void remove_max()
	{
		if(root_ == nullptr) return;
		
		if(!is_red(root_->left) && !is_red(root_->right))
		{
			root_->color = RED;
		}
		
		root_ = remove_max(root_);
		
		if(root_) root_->color = BLACK; 
	}
	
	
	void remove(const _Key & key)
	{
		//判断树中是否存在这个key
		if(!contains(root_, key)) return;
		
		if(!is_red(root_->left) && !is_red(root_->right))
		{
			root_->color = RED;
		}
		
		root_ = remove(root_, key);
		
		if(root_) root_->color = BLACK; 
	}
	
	void print() const
	{
		print(root_);
		std::cout << std::endl;
	}
};

int main()
{
	
	int testCount = 7;
	int keys[] = {6, 7, 1, 5, 3, 4, 2};

	LLRBT<int, int> st;
	
	for(int i = 0; i < testCount; ++i)
	{
		std::cout << "put:" << keys[i] << std::endl;
		st.put(keys[i], keys[i]);
		//st.print();
	}

	for(int j = 1; j <= testCount; ++j)
	{
		st.remove(j);
		
		std::cout << "\nremove:" << j << "\nsize:" << st.size() << std::endl;

		for(int i = 1; i <= testCount; ++i)
		{
			int * p = st.get(i);
			std::cout << (p ? *p : 0) << ' ';
		}
			
		std::cout << std::endl;
		st.print();
		std::cout << std::endl;
	}
	
		
	std::cout << std::endl;

	std::cin.get();
	
	return 0;
}