c++利用红黑树实现map和set


关于红黑树的实现在之前的 博客已经说明了,现在利用红黑树封装一个简单的map和set,有部分代码作了修改。

1. 红黑树的封装

1.1 定义红黑树节点

#pragma once
#include <iostream>

enum Colour {
	Red,
	Black,
};

template<class Value>
struct RBNode {
	RBNode<Value>* _left;
	RBNode<Value>* _right;
	RBNode<Value>* _parent;

	Value _kv;
	Colour _colour;
	
	RBNode(const Value& kv = Value())
		:_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_kv(kv)
	{}
};

1.2 定义迭代器

template <class Value, class Ref, class Ptr>  
struct RBTree_iterator
{
	//typedef RBTree_iterator<Value, Value&, Value*>     iterator;
	//typedef RBTree_iterator<Value, const Value&, const Value*> const_iterator;
	typedef RBTree_iterator<Value, Ref, Ptr>   self;
	typedef RBNode<Value> Node;

	Node* _node;

	RBTree_iterator() {}
	RBTree_iterator(Node* x) 
		:_node(x)
	{}

	//RBTree_iterator(const iterator& it) 
	//	:_node(it._node)
	//{}

	Ref operator*() const { return _node->_kv; }

	Ptr operator->() const { return &(operator*()); }


	self& operator++() 
	{ 
		if (_node->_right)
		{
			_node = _node->_right;
			while (_node->_left)
			{
				_node = _node->_left;
			}
		}
		else
		{
			Node* parent = _node->_parent;
             //中序 左->中->右,当访问的节点在父亲的右边,说明父亲已经被访问了,应该访问父亲的父亲。
			while (_node == parent->_right) 
			{
				_node = parent;
				parent = parent->_parent;
			}
			if(_node->_right != parent )
				_node = parent;
		}
		return *this;
	}

	//self& operator--()   //右->中->左
	//{ 
	//	if (_node->_left)  //访问左边节点的最右节点
	//	{
	//		_node = _node->_left;
	//		while (_node->_right)
	//		{
	//			_node = _node->_right;
	//		}
	//	}
	//	else //左边节点不存在,访问当前节点的父亲
	//	{
	//		Node* parent = _node->_parent;
	//		while (parent && _node == parent->_left)  
	//		{
	//			_node = parent;
	//			parent = parent->_parent;
	//		}
	//		_node = parent;
	//	}
	//	return *this;
	//}

	//为了重载operator++, 将end()定义了header,实际上的end()应为_header->right
	//定义header的作用在这儿体现

	//另外要注意的是, 这个operator--无法被用户调用,应为会打印出_header->_kv,而且end()为leftmost的最后节点无法访问
	//它的作用可以用来封装反向迭代器。
	self operator--() 
	{
		if (_node->_colour == Red && _node->_parent->_parent == _node) //为header节点
		{
			_node = _node->_right;
		}
		else if (_node->_left)  //左不为空
		{
			Node* min_node = _node->_left;
			while (min_node->_right)
			{
				min_node = min_node->_right;
			}
			_node = min_node;
		}
		else
		{
			Node* parent = _node->_parent;
			while (_node == parent->_left)
			{
				_node = parent;
				parent = parent->_parent;
			}
			_node = parent;
		}
		return *this;
	}

	inline bool operator!=(const self& x)
	{
		return _node != x._node;
	}
};

1.3 红黑树改写

// Value:对于 set来说是key类型,对于map是pair;KeyOfValue:用来取出map和set中的key,是个仿函数
template <class Key, class Value, class KeyOfValue> 
class RBTree 
{
	typedef RBNode<Value> Node;
private:
	Node* LeftMost() const
	{
		Node* leftmost = _header->_left;

		return leftmost;
	}

	Node* RightMost() const
	{
		Node* rightmost = _header->_right;

		return rightmost;
	}
public:
	typedef RBTree_iterator<Value, Value&, Value*> const_iterator;

	const_iterator begin() const
	{
		return const_iterator(LeftMost());
	}

	const_iterator end() const
	{
		return const_iterator(_header);
	}


public:
	RBTree()
		:_root(nullptr)
	{
		_header = new Node;
		_header->_colour = Red;  //将header的颜色设为红色,用来标记
	}

	bool _RBtree_Insert(const Value& kv)
	{
		Node* newnode = new Node(kv);
		if (_header->_parent == nullptr)
		{
			_root = newnode;

			_header->_parent = _root;
			_root->_parent = _header;

			_header->_left = _root;
			_header->_right = _root;
			_root->_colour = Black;

			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur) // 找插入的位置
		{
			//if (cur->_kv.first > kv.first)
			 //使用KeyOfValue()构造的仿函数匿名对象去除key值,将cur的key值和插入的节点key进行比较
			if(KeyOfValue()(cur->_kv) > KeyOfValue()(kv)) 
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (KeyOfValue()(cur->_kv) < KeyOfValue()(kv))
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;  //找不到返回,找到了执行插入操作;等于的情况有冗余,不执行插入
			}
		}

		cur = newnode;
		cur->_colour = Red; //插入红色的节点

		//if (parent->_kv.first > kv.first)
		if(KeyOfValue()(parent->_kv) > KeyOfValue()(kv))
		{
			parent->_left = newnode;
			newnode->_parent = parent;
		}
		else  //不存在等于情况,等于上面已经返回了
		{
			parent->_right = newnode;
			newnode->_parent = parent;
		}
		// 调整部分
		while (parent && parent->_colour == Red) //父节点存在且为红,有连续的红节点,继续向上调整
		{
			Node* grandparent = parent->_parent;
			if (grandparent->_left == parent)  // 先考虑父节点在左的情况
			{
				Node* uncle = grandparent->_right;
				if (uncle && uncle->_colour == Red)  //叔叔存在且为红,继续向上调整。
				{
					parent->_colour = Black;
					uncle->_colour = Black;
					grandparent->_colour = Red;
				}
				else //叔叔存在且为黑 或者 叔叔不存在
				{
					if (cur == parent->_left) //cur、parent、grandparent三个节点在一条直线上,右单旋
					{
						RotateR(grandparent);
						grandparent->_colour = Red;
						parent->_colour = Black;
					}
                    // cur、parent、grandparent三个节点在折直线上,先以parent进行左单旋,然后以grandparent进行右单旋
					else 
					{
						RotateL(parent);
						RotateR(grandparent);
						cur->_colour = Black;
						grandparent->_colour = Red;
					}
					break; //调整后
				}
			}
			else  //父节点在grandparent的右
			{
				Node* uncle = grandparent->_left;
				if (uncle && uncle->_colour == Red)  //叔叔存在且为红,继续向上调整。
				{
					parent->_colour = Black;
					uncle->_colour = Black;
					grandparent->_colour = Red;
				}
				else //叔叔存在且为黑 或者 叔叔不存在
				{
					if (cur == parent->_right) //cur、parent、grandparent三个节点在一条直线上,左单旋
					{
						RotateL(grandparent);
						grandparent->_colour = Red;
						parent->_colour = Black;
					}
                    // cur、parent、grandparent三个节点在折直线上,先以parent进行右单旋,然后以grandparent进行左单旋
					else 
					{
						RotateR(parent);
						RotateL(grandparent);
						cur->_colour = Black;
						grandparent->_colour = Red;
					}
					break; 
				}
			}
		}
		//**************** 更新_header ***************
		Node* leftmost = _root;
		while (leftmost && leftmost->_left)
		{
			leftmost = leftmost->_left;
		}
		_header->_left = leftmost;

		Node* rightmost = _root;
		while (rightmost && rightmost->_right)
		{
			rightmost = rightmost->_right;
		}
		_header->_right = rightmost;

		_root->_parent = _header;  //注意调整root,因为旋转后root可能发生了变化
		_header->_parent = _root;
		//********************************************
		_root->_colour = Black;  //将根节点置黑
		return true;
	}

	void RotateR(Node* parent)
	{
		Node* pleft = parent->_left;
		Node* pleftR = pleft->_right;
		Node* parentParent = parent->_parent;

		parent->_parent = pleft;
		pleft->_right = parent;

		if (pleftR) //Pleft_Right若为nullptr,则无法找到其parent
		{
			pleftR->_parent = parent;
		}
		parent->_left = pleftR;

		if (parent == _root) //若原来的parent为根,则将pleft更新为根节点
		{
			_root = pleft;
			_root->_parent = nullptr;
		}
		else // parent不为根节点,则其存在父节点,将pleft的父节点与原来parent的父节点进行链接
		{
			if (parentParent->_left == parent)
			{
				parentParent->_left = pleft;
			}
			else
				parentParent->_right = pleft;
			pleft->_parent = parentParent;
		}
	}
	
	void RotateL(Node* parent)
	{
		Node* pright = parent->_right;
		Node* prightL = pright->_left;
		Node* parentParent = parent->_parent;

		parent->_parent = pright;
		pright->_left = parent;

		if (prightL)
		{
			prightL->_parent = parent;
		}
		parent->_right = prightL;

		if (parent == _root)
		{
			_root = pright;
			_root->_parent = nullptr;
		}
		else
		{
			if (parentParent->_left == parent)
			{
				parentParent->_left = pright;
			}
			else if (parentParent->_right == parent)
			{
				parentParent->_right = pright;
			}
			pright->_parent = parentParent;
		}
	}
	Node* returenROOT()
	{
		return _header->_parent;
	}

private:
	Node* _root;
	Node* _header;
};

2. map和set的封装

2.1 map.h

#pragma once

#include "RBTree.h"

template <class Key, class T>
class map
{
public:
	typedef Key key_type;
	typedef std::pair<const Key, T> value_type;

	//typedef RBTree<Key, Value, KeyOfValue> rep_type;
	//typedef tpedname rep_type::const_iterator iterator;

private:
	struct KeyOfValueFunc   //定义一个仿函数,取出红黑树的key值
	{
		const key_type& operator()(const value_type& k) const
		{
			return k.first;
		}
	};
	typedef RBTree <key_type, value_type, KeyOfValueFunc> RBTreeType;
	RBTreeType _t;

public:
	typedef typename RBTree<key_type, value_type, KeyOfValueFunc>::const_iterator iterator;

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

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

public:
	bool insert(const value_type& kv)
	{
		return _t._RBtree_Insert(kv);
	}
};

2.2 set.h

#pragma once

#include "RBTree.h"

template <class Key>
class set
{
public:
	typedef Key key_type;
	typedef Key value_type;

private:
	struct KeyOfValueFunc   //定义一个仿函数,取出红黑树的key值
	{
		const key_type& operator()(const key_type& k) const
		{
			return k;
		}
	};
	typedef RBTree <key_type, value_type, KeyOfValueFunc> RBTreeType;
	RBTreeType _t;  //set的成员变量是一棵红黑树

public:

	typedef typename RBTree<key_type, value_type, KeyOfValueFunc>::const_iterator iterator;

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

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

public:
	bool insert(const Key& key)
	{
		return _t._RBtree_Insert(key);
	}

	typedef RBNode<value_type> Node;

	Node* returenROOT()
	{
		return _t.returenROOT();
	}
};

3. 测试程序

#define _CRT_SECURE_NO_WARNINGS 1
#include <vector>
#include <iostream>
#include "set.h"
#include "map.h"

void PrintSingleNode(FILE* pFile, RBNode<int>* root)
{
	if (root->_colour == Black)
	{
		fprintf(pFile, "\tnode[shape=record,style=\"rounded, filled\",color=black,fontcolor=white, weight = 20];\n");
	}
	else
	{
		fprintf(pFile, "\tnode[shape=record,style=\"rounded, filled\",color=red,fontcolor=white,  weight = 20];\n");
	}
	fprintf(pFile, "\t%d[label=\"<f0> | <f1> %d | <f2> \", labelfontsize = 20];\n", root->_kv, root->_kv);
}

void WriteTree2File(FILE* pFile, RBNode<int>* root, RBNode<int>* Header)
{
	
	if (nullptr == root) return;
	if (root->_parent == Header)
	{
		PrintSingleNode(pFile, root);
	}

	if (root->_left != nullptr)
	{
		PrintSingleNode(pFile, root->_left);
		fprintf(pFile, "\t%d:f0:sw->%d:f1;\n", root->_kv, root->_left->_kv);
	}
	if (root->_right != nullptr)
	{
		PrintSingleNode(pFile, root->_right);
		fprintf(pFile, "\t%d:f2:se->%d:f1;\n", root->_kv, root->_right->_kv);
	}
	WriteTree2File(pFile, root->_left, Header);
	WriteTree2File(pFile, root->_right, Header);
}


int main()
{
	set<int> t;
	map<int, int> m;
	int a[] = { 20,30,35,14,26, 24 ,28, 22 ,36,32};
	for (auto e : a)
	{
		t.insert(e);
		m.insert(std::make_pair(e, e*e));
	}

	std::cout << "Test For My set!" << std::endl;
	set<int>::iterator it = t.begin();
	while (it != t.end())
	{
		std::cout << *it << " ";
		++it;
	}

	std::cout << std::endl;

	std::cout << "Test For My map!" << std::endl;

	map<int, int>::iterator itm = m.begin();
	while (itm != m.end())
	{
		std::cout << itm->first << "->" << itm->second << " ";
		++itm;
	}

	FILE* fp;
	fp = fopen("RBTree.dot", "w+");
	fprintf(fp, "digraph G{\n");
	WriteTree2File(fp, t.returenROOT(), t.returenROOT()->_parent);
	fprintf(fp, "}");
	fclose(fp);

	system("dot -Tpng -O RBTree.dot");
	system("RBTree.dot.png");

	return 0;
}

结果展示
在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值