红黑树(左倾)C++

红黑树的性质:
1.每个结点的链接要么是红的要么是黑的;
2.根结点的链接是黑的;
3.每个叶结点的左右nullptr指针都是黑的;
4.如果一个父节点链接是红的,那么它的两个儿子的链接都是黑的;
5.对于任意结点而言,其到叶结点树尾端到根节点的每条路径都包含相同数目的黑链接。

#include<iostream>
#define RED true
#define BLACK false

template<class T>
class TreeNode
{
public:
	T m_nkey;
	int m_nValue;
	int N;
	bool color;
	TreeNode* pLeft, * pRight;
	TreeNode(T _key, int _value, int _N, bool _color)
		:m_nkey(_key), m_nValue(_value), N(_N),color(_color), pLeft(nullptr), pRight(nullptr) {}
};

template<class Key>
class RedBlackTree
{
	TreeNode<Key>* pRoot;
public:
	RedBlackTree() :pRoot(nullptr) {};
	~RedBlackTree() { clear(); }
	int size();//树节点数量
	void put(Key _key, int _value);//插入新节点
	void printfTree() { _printfTree(pRoot); }//打印树
	void deleteMin();//删除最小键
	void deleteMax();//删除最大键
	void deleteNode(Key key);//删除节点
	void clear() { _clear(pRoot); }//手动销毁树
private:
//******************************************************************************
	//辅助方法
//******************************************************************************
	void _printfTree(TreeNode<Key>* root){
		if (root)
		{
			std::cout << "(" << root->m_nkey << "," << root->color << ")" << " ";
			_printfTree(root->pLeft);
			_printfTree(root->pRight);
		}
	}
	void _clear(TreeNode<Key>*& root);
	TreeNode<Key>* _put(TreeNode<Key>* root, Key _key, int _value);
	TreeNode<Key>* _deleteMin(TreeNode<Key>* root);
	TreeNode<Key>* _deleteMax(TreeNode<Key>* root);
	TreeNode<Key>* _deleteNode(TreeNode<Key>* root, Key _key);
	TreeNode<Key>* moveNodeLeft(TreeNode<Key>* node);
	TreeNode<Key>* moveNodeRight(TreeNode<Key>* node);
	TreeNode<Key>* _getMin(TreeNode<Key>* root);
	int _getValue(TreeNode<Key>* node,Key key);
	int _size(TreeNode<Key>* node);
	bool isRed(TreeNode<Key>* node);
	void flipColor(TreeNode<Key>* node);
	TreeNode<Key>* rotateLeft(TreeNode<Key>* node);
	TreeNode<Key>* rotateRight(TreeNode<Key>* node);
	TreeNode<Key>* blance(TreeNode<Key>* node);
};

//******************************************************************************
	//方法实现
//******************************************************************************
template<class Key>
void RedBlackTree<Key>::_clear(TreeNode<Key>*& root)
{//此处递归删除时要引用,否则内存不会为NULL
	if (root)
	{
		_clear(root->pLeft);
		_clear(root->pRight);
		delete root;
		root = nullptr;
	}
}
template<class Key>
void RedBlackTree<Key>::put(Key _key, int _value)
{
	pRoot = _put(pRoot, _key, _value);
	pRoot->color = BLACK;//红黑树性质:根节点为黑色
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_put(TreeNode<Key>* root, Key _key, int _value)
{
	if (root == nullptr)
		return root = new TreeNode<Key>(_key, _value, 1, RED);//如果没有这个节点则new块内存出来
	if (_key < root->m_nkey)root->pLeft = _put(root->pLeft, _key, _value);//左递归
	else if (_key > root->m_nkey)root->pRight = _put(root->pRight, _key, _value);//右递归
	else root->m_nValue = _value;
	if (isRed(root->pRight) && !isRed(root->pLeft))root = rotateLeft(root);//第一层变换,当右节点链接为红色时左旋
	if (isRed(root->pLeft) && isRed(root->pLeft->pLeft))root = rotateRight(root);//第二层变换,不允许出现4-节点,即没有两根连续的红色链接
	if (isRed(root->pLeft) && isRed(root->pRight))flipColor(root);//第三层变换,当节点的左右子节点链接都为红色时,将链接颜色转换
	root->N = _size(root->pLeft) + _size(root->pRight) + 1;//更新节点数量
	return root;
}
template<class Key>
void RedBlackTree<Key>::deleteNode(Key key)
{
	if (pRoot)
	{//一定要在树不为空的情况下进行
		if (!isRed(pRoot->pLeft) && !isRed(pRoot->pRight))//这个点可加,可不加,算是一种约定俗成
			pRoot->color = RED;
		pRoot = _deleteNode(pRoot, key);
		if (pRoot)pRoot->color = BLACK;//根节点默认黑色
	}
	else
	{
		std::cout << "树为空!" << std::endl;
		return;
	}
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_deleteNode(TreeNode<Key>* root, Key _key)
{   //结合删除最小节点和删除最大节点
	if (root)
	{
		if (_key < root->m_nkey)
		{//往左左子树走

			if (root->pLeft && !isRed(root->pLeft) && !isRed(root->pLeft->pLeft))
				root = moveNodeLeft(root);
			root->pLeft = _deleteNode(root->pLeft, _key);
		}
		else
		{//往右子树走
			if (isRed(root->pLeft))
				root = rotateRight(root);
			if (_key == root->m_nkey && root->pRight == nullptr)
			{//当节点为最右节点时,可直接删除
				delete root;
				return nullptr;
			}
			//判断该点是否是2-节点
			if (root->pRight && !isRed(root->pRight) && !isRed(root->pRight->pLeft))
				root = moveNodeRight(root);
			if (_key == root->m_nkey)
			{//在树中找到节点,则用右子树的最小节点代替,然后删除掉左子树的最小节点
				root->m_nValue = _getValue(root->pRight, _getMin(root->pRight)->m_nkey);
				root->m_nkey = _getMin(root->pRight)->m_nkey;
				root->pRight = _deleteMin(root->pRight);
			}
			else root->pRight = _deleteNode(root->pRight, _key);
		}
	}
	else
	{
		std::cout << "节点不存在!!!" << std::endl;
	}
	return blance(root);
}
template<class Key>
void RedBlackTree<Key>::deleteMin()
{
	if (pRoot)
	{//同删除
		if (!isRed(pRoot->pLeft) && !isRed(pRoot->pRight))
			pRoot->color = RED;
		pRoot = _deleteMin(pRoot);
		if (pRoot)pRoot->color = BLACK;
	}
	else
	{
		std::cout << "树为空!" << std::endl;
		return;
	}
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_deleteMin(TreeNode<Key>* root)
{
	if (root->pLeft == nullptr)
	{
		delete root;
		return nullptr;
	}
	//判断是否为2-节点
	if (!isRed(root->pLeft) && !isRed(root->pLeft->pLeft))
		root = moveNodeLeft(root);//如果是2-节点,就变成一个3-节点
	root->pLeft = _deleteMin(root->pLeft);
	return blance(root);
}
template<class Key>
void RedBlackTree<Key>::deleteMax()
{
	if (pRoot)
	{//同删除
		if (!isRed(pRoot->pLeft) && !isRed(pRoot->pRight))
			pRoot->color = RED;
		pRoot = _deleteMax(pRoot);
		if (pRoot)pRoot->color = BLACK;
	}
	else
	{
		std::cout << "树为空!" << std::endl;
		return;
	}
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_deleteMax(TreeNode<Key>* root)
{
	if (isRed(root->pLeft))//删除最大节点,如果该节点为3-节点 进行右旋,为后面的父节点往下走形成3-节点形成条件
		root = rotateRight(root);
	if (root->pRight == nullptr)
	{
		delete root;
		return nullptr;
	}
	//判断是否为2-节点
	if (!isRed(root->pRight) && !isRed(root->pRight->pLeft))
		root = moveNodeRight(root);
	root->pRight = _deleteMax(root->pRight);
	return blance(root);
}
template<class Key>
int RedBlackTree<Key>::size()
{
	return _size(pRoot);
}
template<class Key>
int RedBlackTree<Key>::_size(TreeNode<Key>* node)
{
	if (node == nullptr)return NULL;
	return node->N;
}
template<class Key>
bool RedBlackTree<Key>::isRed(TreeNode<Key>* node)
{//判断是否为红链接
	if (node == nullptr)return false;
	return node->color==RED;
}
template<class Key>
void RedBlackTree<Key>::flipColor(TreeNode<Key>* node)
{/*方法作用:
   1、当左右链接为红时,进行变化
   2、向父节点借节点
   3、还给父节点节点
 */
	node->color = !node->color;
	node->pLeft->color = !node->pLeft->color;
	if(node->pRight)
	node->pRight->color = !node->pRight->color;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::rotateLeft(TreeNode<Key>* node)
{//左旋
	TreeNode<Key>* x = node->pRight;                               
	node->pRight = x->pLeft;                                       
	x->pLeft = node;                                              
	x->color = x->pLeft->color;                                    
	x->pLeft->color = RED;                                         
	x->N = node->N;                                                
	node->N = _size(node->pLeft) + _size(node->pRight) + 1;     
	return x;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::rotateRight(TreeNode<Key>* node)
{//右旋
	TreeNode<Key>* x = node->pLeft;
	node->pLeft = x->pRight;
	x->pRight = node;
	x->color = x->pRight->color;
	x->pRight->color = RED;
	x->N = node->N;
	node->N = _size(node->pLeft) + _size(node->pRight) + 1;
	return x;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::blance(TreeNode<Key>* node)
{//平衡
	if (node)
	{
		if (node->pRight)node = rotateLeft(node);
		if (isRed(node->pLeft) && isRed(node->pLeft->pLeft))node = rotateRight(node);
		if (isRed(node->pLeft) && isRed(node->pRight))flipColor(node);
		node->N = _size(node->pLeft) + _size(node->pRight) + 1;
	}
	return node;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::moveNodeLeft(TreeNode<Key>* node)
{
	flipColor(node);//向父节点借一个节点,变成3-节点
	if (node->pRight && isRed(node->pRight->pLeft))
	{//如果兄弟节点存在且不为2-节点,则从兄弟节点借节点过来
		node->pRight = rotateRight(node->pRight);
		node = rotateLeft(node);
		flipColor(node);
	}
	return node;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::moveNodeRight(TreeNode<Key>* node)
{//同上
	flipColor(node);
	if (node->pLeft && isRed(node->pLeft->pLeft))
	{
		node = rotateRight(node);
		flipColor(node);
	}
	return node;
}
template<class Key>
int RedBlackTree<Key>::_getValue(TreeNode<Key>* node, Key _key)
{
	if (_key < node->m_nkey) return _getValue(node->pLeft,_key);
	else if (_key > node->m_nkey)return _getValue(node->pRight,_key);
	else return node->m_nValue;
}
template<class Key>
TreeNode<Key>* RedBlackTree<Key>::_getMin(TreeNode<Key>* node)
{
	if (node->pLeft == nullptr)return node;
	else return _getMin(node->pLeft);
}


int main(int argc, char* argv[])
{
	RedBlackTree<char> B;
	B.put('A', 10);
	B.put('B', 10);
	B.put('C', 10);
	B.put('D', 10);
	B.printfTree();
	std::cout << "\n";
	B.deleteNode('D');
	B.printfTree();
	//std::cout << "\n";
	//B.deleteNode('A');
	//B.printfTree();
	std::cin.get();
	return 0;
}

(●新手一枚,有错误之处请大佬多多指正●)

发布了107 篇原创文章 · 获赞 28 · 访问量 1953

猜你喜欢

转载自blog.csdn.net/qq_38994205/article/details/104621571