手動編程實現紅黑樹,並給出與set差不多的接口。

寫一個自己想要的“set”,想實現什麼功能直接在裏面添加。STL雖然把set封裝的很好,很強大,易於擴展,但是正由於兼容性很好,封裝太多層,犧牲了很多性能。下面是我的測試結果

void test(int num) {
	time_t rawtime;
	time(&rawtime);
	struct tm * ti = localtime(&rawtime);
	
	int v[10000];

	RBTree<int> t;
	multiset<int> s;
	int time1 = ti->tm_min * 60 + ti->tm_sec;
	cout << "RBtree開始插入數據,當前時間:" << time1 << "秒" << endl;

	for (int i = 0; i < num; i++) {
		int a = rand() % INT_MAX;
		t.RBTree_insert(a);
		//s.insert(a);
	}	
	time(&rawtime);
	ti = localtime(&rawtime);
	cout << "插入完成,當前時間:" << ti->tm_min * 60 + ti->tm_sec << ",RBtree用時:"
		<< ti->tm_min * 60 + ti->tm_sec - time1<< "秒" << endl;
	time1 = ti->tm_min * 60 + ti->tm_sec;
	time(&rawtime);
	ti = localtime(&rawtime);
	cout << "set開始插入數據,當前時間:" << time1 << "秒" << endl;
	for (int i = 0; i < num; i++) {
		int a = rand() % INT_MAX;
		s.insert(a);
	}	
	time(&rawtime);
    ti = localtime(&rawtime);
	cout << "插入完成,當前時間:" << ti->tm_min * 60 + ti->tm_sec << ",set用時:"
		<< ti->tm_min * 60 + ti->tm_sec - time1<<"秒"<<endl;
	//t.mid_traverse();
	cout << endl;
	int cnt = 0;
	cout << "xigou" << endl;
}
int main() {

	test(pow(10, 7));
	
	return 0;
	//system("pause");
}

我分別用自己的設計的RBtree與STL的multiset分別插入100萬數據,下面是運行時間:

RBtree用時28秒,set用時166秒,是RBtree的5到6倍,這個差距已經不小了。

下面是我的代碼:

#pragma once
#include<iostream>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
enum color
{
	red,
	black
};
template<typename T>
struct RB_TreeNode 
{
	RB_TreeNode * left;
	RB_TreeNode * right;
	RB_TreeNode * p;
	static RB_TreeNode<T> * _Guard;
	T val;
	color color;
	RB_TreeNode (T x) :val(x), left(_Guard), right(_Guard), p(_Guard), color(red) {};
	RB_TreeNode () : left(NULL), right(NULL), p(NULL), color(black) {};
	void operator=(RB_TreeNode<T>& oth) {
		left = oth.left;
		color = oth.color;
		right = oth.right;
		val = oth.val;
		p = oth.p;
	}
};
template<typename T>
RB_TreeNode<T>* RB_TreeNode<T>::_Guard = new RB_TreeNode<T>();

template<typename T>
class RBTree
{	
public:
	
	RBTree()
	{
		_root = _guard;
		_len = 0;
	}
	RBTree(vector<T> v)
	{
		_root = _guard;
		_len = 0;
		for (int i = 0; i < v.size(); i++)
		{
			RBTree_insert(v[i]);
		}
	}
	RBTree(const RBTree<T>& oth) {
		_root = copyTree(oth, _guard);
	}
	//移動構造函數
	RBTree(RBTree<T>&& oth) {		
		_root = oth._root;
	}

	RB_TreeNode<int>* guard() {
		return _guard;
	}
	bool operator=(RBTree<T>& oth) {
		clear();//在拷貝之前,先要釋放已有資源
		_root = copyTree(oth, _guard);
	}
	//當參數爲右值引用
	bool operator=(RBTree<T>&& oth) {
		clear();//在指向傳進來的節點之前,要先釋放原來的資源;
		_root = oth.root;
	}
	~RBTree()
	{
		clear();
	}
	void clear() {
		if (_root == NULL)
		{
			_len = 0;
			return;
		}
		cout << "開始釋放已有資源" << endl;
		distroy(_root);
		_root = NULL;
		_len = 0;
	}
	int size()
	{
		return _len;
	}
	RB_TreeNode<T> * getroot()
	{
		return _root;
	}
	////插入節點
	void RBTree_insert(int value)
	{		
		RB_TreeNode<T> * Tnode = new RB_TreeNode<T> (value);
		RB_TreeNode<T> * tmp = _root;
		RB_TreeNode<T> * Ptmp =_guard;
		if (_root == _guard)
		{
			_root = Tnode;
			_root->color = black;
			_len++;
			return;
		}
		while (tmp!= _guard)
		{
			Ptmp = tmp;
			if (tmp->val > value)
				tmp = tmp->left;
			else
				tmp = tmp->right;
	    }
		Tnode->p = Ptmp;
		if (Tnode->val < Ptmp->val)
			Ptmp->left = Tnode;
		else
			Ptmp->right = Tnode;
		if(Tnode->p->color==red)
		RBINSERT_Fixup(Tnode);
		_len++;
    }
    ///調整紅黑樹滿足紅黑樹五個特性
	void RBINSERT_Fixup(RB_TreeNode<T> * t)
	{
		RB_TreeNode<T> * tmp = t->p;
		RB_TreeNode<T> * Pbra = _guard;
		while (tmp->color==red)
		{
			if (tmp == tmp->p->left)
			{
				Pbra = tmp->p->right;
				if (Pbra!=_guard&&Pbra->color == red)
				{
					tmp->color = black;
					tmp->p->color = red;
					Pbra->color = black;
					t = tmp->p;
					tmp = t->p;
				}
				else
				{
					if (t == tmp->right)
					{
						Left_Rotate(tmp);
						tmp = t;
					}
					tmp->color = black;
					tmp->p->color = red;
					Right_Rotate(tmp->p);
				}							
			}
			else
			{
				Pbra = tmp->p->left;
				if (Pbra!=_guard&&Pbra->color == red)
				{
					tmp->color = black;
					tmp->p->color = red;
					Pbra->color = black;
					t = tmp->p;
					tmp = t->p;
				}
				else
				{
					if (t == tmp->left)
					{
						Right_Rotate(tmp);
						tmp = t;
					}
					tmp->color = black;
					tmp->p->color = red;
					Left_Rotate(tmp->p);
				}
			}
			if (tmp==_guard)
			{
				tmp = t;
				tmp->color = black;
			}
		}		
	}
    /////刪除節點
	void RBTree_delete(int value)
	{
		RB_TreeNode<T> * t = RBTree_serch(value);
		if (!t) return;
		RB_TreeNode<T> * tmp;
		if (t->left&&t->right)
		{
			t->val = findSucceed(t)->val;
			t = findSucceed(t);
		}	
		if (!t->left)
			tmp = t->right;	
		else 
			tmp = t->left;
		if (!t->p) _root = tmp;
		else if (t == t->p->left)
			    t->p->left = tmp;
			else
				t->p->right = tmp;	
			tmp->p = t->p;
		if (t->color==black)
		{
			RBDELETE_Fixup(tmp);
		}
		_len--;
		delete t;
		t = NULL;
		return;
	}
	///調整紅黑樹滿足紅黑樹五個特性
	void RBDELETE_Fixup(RB_TreeNode<T> * t)
	{
		RB_TreeNode<T> * w = NULL;
		while (t!=_root&&t->color==black)
		{
			if (t == t->p->left)
			{
				w = t->p->right;
				if (w->color == red)
				{
					t->p->color = red;
					w->color = black;
					Left_Rotate(t->p);
				}
				else
				{
					if (w->right!=_guard&&w->right->color == red)
					{
						w->color = t->p->color;
						t->p->color = black;
						w->right->color = black;
						Left_Rotate(t->p);
						t = _root;
					}
					else if (w->left != _guard&&w->left->color == red)
					{
						w->color = red;
						w->left->color = black;
						Right_Rotate(w);
						w = w->p;
					}
					else
					{
						w->color = red;
						t = t->p;
					}

				}
			}
			else
			{
				w = t->p->right;
				if (w->color == red)
				{
					t->p->color = red;
					w->color = black;
					Right_Rotate(t->p);
				}
				else
				{
					w = t->p->left;
					if (w->left != _guard&&w->left->color == red)
					{
						w->color = t->p->color;
						t->p->color = black;
						w->left->color = black;
						Right_Rotate(t->p);
						t = _root;
					}
					else if (w->right != _guard&&w->right->color == red)
					{
						Left_Rotate(w);
						w = w->p;
					}
					else
					{
						w->color = red;
						t = t->p;
					}
				}
			}
		}
		t->color = black;
	}
    /////尋找節點
	RB_TreeNode<T> *  RBTree_serch(int value)
	{
		RB_TreeNode<T> * p = _root;
		while (p != _guard)
		{
			if (p->val == value) return p;
			if (p->val < value)
				p = p->right;
			else 
				p = p->left;
		}
		return p;
	}
	///////尋找前驅
	RB_TreeNode<T> * findFront(RB_TreeNode<T> * t)
	{
		if (t == _guard) return t;
		if (t->left != _guard)
		{
			RB_TreeNode<T> * tmp = t->left;
			while (tmp->right != _guard)
				tmp = tmp->right;
			return tmp;
		}
		else
		{
			RB_TreeNode<T> * tmp = t->p;
			if (tmp == _guard ||t == tmp->right)
				return tmp;
			while (tmp->p != _guard&&tmp == tmp->p->left)
				tmp = tmp->p;
			 return tmp->p;
		}
	}
	/////尋找後繼
	RB_TreeNode<T> * findSucceed(RB_TreeNode<T> * t)
	{
		if (t == _guard) return t;
		if (t->right != _guard)
		{
			RB_TreeNode<T> * tmp = t->right;
			while (tmp->left != _guard)
				tmp = tmp->left;
			return tmp;
		}
		else
		{
			RB_TreeNode<T> * tmp = t->p;
			if (tmp != _guard || t == tmp->left)
				return tmp;
			while (tmp->p != _guard&&tmp == tmp->p->right)
				tmp = tmp->p;
			return tmp->p;
		}
	}
	//////左旋
	void Left_Rotate(RB_TreeNode<T> * t)
	{
		if (t == _guard || t->right == _guard)
		{
			cout << "左旋節點或節點右孩子不應爲空" << endl;
			return;
		}
		RB_TreeNode<T> * tmp = t->right;
		tmp->p = t->p;
		if (t->p==_guard)
		{ 
			_root = tmp;
		}
		else if (t == t->p->left)
			t->p->left = tmp;
		else
			t->p->right = tmp;
		t->p = tmp;
		t->right = tmp->left;
		if(tmp->left != _guard)
		tmp->left->p = t;
		tmp->left = t;
	}
	////右旋
	void Right_Rotate(RB_TreeNode<T> * t)
	{
		if (!t || !t->left)
		{
			cout << "右旋節點或節點左孩子不應爲空" << endl;
			return;
		}
		RB_TreeNode<T> * tmp = t->left;
		tmp->p = t->p;
		if(t->p==_guard)
		{
			_root = tmp;
		}
		else if (t == t->p->left)
			t->p->left = tmp;
		else
			t->p->right = tmp;
		t->p = tmp;		
		t->left = tmp->right;
		if(tmp->right != _guard)
		tmp->right->p = t;
		tmp->right = t;
	}
	/////前序遍歷
	void pre_traverse()
	{

	}
	////中序遍歷
	void mid_traverse(int* pt=NULL)
	{
		RB_TreeNode<T> * p = _root;
		stack<RB_TreeNode<T> *> s;
		while (true)
		{
			while (p!=_guard)
			{
				s.push(p);
				p = p->left;
			}

			if (s.empty()) break;
			p = s.top();
			if (pt == NULL)
				cout << p->val << " ";
			else
				*(pt++) = p->val;
			s.pop();
			p = p->right;
		}
	}
	/////後序遍歷
	void post_traverse() {

	}
	/////層次遍歷
	void Print() {	
		RB_TreeNode<T> * pRoot = _root;
		if (!pRoot) return ;
		vector<queue<RB_TreeNode<T> *> > vq(2);
		int index = 0;
		vq[index].push(pRoot);
		while (!vq[index].empty() || !vq[1 - index].empty())
		{
			while (!vq[index].empty())
			{
				RB_TreeNode<T> * p = vq[index].front();
				vq[index].pop();
				cout << p << " ";
				if (p->left != _guard)
					vq[1 - index].push(p->left);
				if (p->right != _guard)
					vq[1 - index].push(p->right);
			}
			cout << endl;
			index = 1 - index;
		}
	}
private:
	RB_TreeNode<T> * copyTree(const RB_TreeNode<T>* oth, RB_TreeNode<T>* p) {
		if (oth == _guard) return _guard;
		RB_TreeNode<T>* root = new RB_TreeNode(oth->val);
		root->color = oth->color;
		root->p = p;
		root->left = copyTree(oth->left,root);
		root->right = copyTree(oth->right,root);
		return root;
	}
	void distroy(RB_TreeNode<T>* root) {
		if (root == _guard) return;
		distroy(root->left);
		distroy(root->right);
		delete root;
	}
	static RB_TreeNode<T> * _guard;
	RB_TreeNode<T> * _root;
	int _len;
	//friend ostream& operator<<(ostream &out, RB_TreeNode<T> * outT);

};
template<typename T>
RB_TreeNode<T>* RBTree<T>::_guard = RB_TreeNode<T> ::_Guard;

template<typename T>
ostream& operator << (ostream &out, RB_TreeNode<T> * outT)
{
	if (!outT) return out;
	cout << "[" << " " << "val:" << outT->val << " "; 
	if(outT->color==0)
     cout<< "color:" << "red"<< " ";
	else
	cout << "color:" << "black" << " ";
	if (outT->left != RB_TreeNode<T> ::_Guard)
		cout << "left:" << outT->left->val << " ";
	if (outT->right != RB_TreeNode<T> ::_Guard)
		cout << "right:" << outT->right->val << " ";
	if(outT->p != RB_TreeNode<T> ::_Guard)
		cout << "parent:" << outT->p->val << " ";
	cout << "]";
	return out;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章