红黑树可运行代码C++ 使用无父指针的节点构造

C++实现仅有孩子节点的红黑树

在旋转时用栈存储叔叔父亲祖先等等。
支持基本的插删查。
使用该红黑树编写的Map通过部分OJ,未发现bug。

/* 
此版本无父指针,旋转时用栈确定祖先。
使用该红黑树编写的Map通过部分OJ,未发现bug
*/ 
#include <queue>
#include <vector>
#include <stack> 
#include <iostream>
#include <algorithm>
using namespace std;
#define RefValue -1e8
#define red 0
#define black 1
template<class K, class E>
struct RBNode {
	bool color;
	K key;
 	E data;
	RBNode<K, E> *left, *right;
	RBNode() {
		left = NULL;
		right = NULL;
		color = red;
	}
	RBNode(E d, K k, bool c = red, RBNode<K, E> *l = NULL, RBNode<K, E> *r = NULL) {
		data = d;
		left = l;
		right = r;
		key = k;
		color = c;
	}
};
template<class K, class E>
class RBTree{
public:
	RBNode<K, E> *root;
	size_t _size;
	void RotateL(RBNode<K, E> *&ptr) {
		RBNode<K, E> *subL = ptr;
		ptr = ptr->right;
		subL->right = ptr->left;
		ptr->left = subL;
	}
	void RotateR(RBNode<K, E> *&ptr) {
		RBNode<K, E> *subR = ptr;
		ptr = ptr->left;
		subR->left = ptr->right;
		ptr->right = subR;
	}
	E & Search(RBNode<K, E> *&ptr, K k, bool& found) {
		E tmp();
		RBNode<K, E> *cur = ptr;
		while (cur != NULL) {
			if (k == cur->key) {
				found = true;
				return cur->data;
			}
			else if (k < cur->key) cur = cur->left;
			else cur = cur->right;
		}
		found = false;
		return tmp;
	}
	bool Insert(RBNode<K, E> *&ptr, E d, K k) {
		RBNode<K, E> *cur = NULL, *p = NULL, *pp = NULL;
		if (ptr == NULL) {
			ptr = new RBNode<K, E>(d, k, black);
			++_size;
			return true;
		}
		stack<RBNode<K, E> *> st;
		cur = ptr;
		while (cur != NULL) {
			st.push(cur);
			pp = p;
			p = cur;
			if (k == cur->key) return false;
			else if (k < cur->key) cur = cur->left;
			else cur = cur->right;
		}
		cur = new RBNode<K, E>(d, k, red);
		++_size;
		if (k < p->key) {
			p->left = cur;
		}
		else p->right = cur;
		if (p->color == black) return true;
		while(st.top() != pp) {
			st.pop();
		}
		st.pop();
		while (true) {
			RBNode<K, E> *uncle = (pp->left == p) ? pp->right : pp->left;
			if (p->color == black) break; 
	  		else if (uncle != NULL && uncle->color == red) {
				pp->left->color = pp->right->color = black;
				if (pp == root) break;
				pp->color = red;
				cur = pp;
			} 
			else if (uncle == NULL || uncle->color == black) {
				RBNode<K, E> *orgpp = pp; //原先的pp 
				if (pp->left == p) {
					if (cur == p->right) {
						RotateL(p);
						pp->left = p;
						cur = p->left;
					}
					pp->color = red;
					p->color = black;
					RotateR(pp); 
				}
				else if (pp->right == p) {
					if (cur == p->left) {
						RotateR(p);
						pp->right = p;
						cur = p->right;	
					}
					pp->color = red;
					p->color = black;
					RotateL(pp); 
				}
				if (st.empty()) {
					root = pp;
				}
				else {
					RBNode<K, E> *ppp = st.top();
					if (ppp->left == orgpp) ppp->left = pp;
					else ppp->right = pp;
				}
				break;
			}
			p = st.top();//注意此时栈一定不空,如果空的话,前面一定break掉了,所以可以果断弹出 
			st.pop();
			if (!st.empty()) { //这时候栈空不空就要看命了,如果这时候栈空,那么p就是root,下一次循环直接break,用不到pp 
				pp = st.top();
				st.pop();
			}
		}
		return true;
	}
	bool Remove(RBNode<K, E> *&ptr, K k) {
		/*第一步是要找到删除节点*/
		RBNode<K, E> *cur = NULL, *p = NULL, *brother = NULL;
		stack<RBNode<K, E> *> st;
		cur = ptr;
		while (cur != NULL) {
			st.push(cur);
			p = cur;
			if (k == cur->key) {
				break;
			}
			else if (k < cur->key) cur = cur->left;
			else cur = cur->right;
		}
		if (cur == NULL) {
			//cout << cur << endl; 
			return false;
		}
		--_size;
		if (st.top() == root && root->left == NULL && root->right == NULL) {
			delete root;
			root = NULL;
			return true;
		}
		/*锁定替代节点,要求是叶节点或者只挂载一个孩子*/
		if (cur->left != NULL && cur->right != NULL) {
			RBNode<K, E> *subT = cur->right; //subT将是cur在中序下的后继节点,中序后继一定在右子树上
			p = cur;
			stack<RBNode<K, E> *> inOrderst;
			/*下面这个循环是迭代寻找中序后继*/
			while (subT != NULL || !inOrderst.empty()) {
				if (subT != NULL) {
					inOrderst.push(subT);
					st.push(subT); 
					subT = subT->left;
				}
				else {
					subT = inOrderst.top();		
					break;
				}
			}
			cur->data = subT->data;
			cur->key = subT->key;
			//cout << cur->key << "replace\n";
			cur = subT; 
		} 
		/*待删节点有一个孩子,待删节点肯定是黑色,而且这个孩子肯定是红色。
		处理方式是待删节点父节点接上这个孩子,这个孩子置黑 
		如果这个待删节点是通过上面找后继找出来的,如果这个待删节点有一个孩子,一定是右孩子*/
		st.pop();
		if (!st.empty()) {
			p = st.top();//将p赋值为代替节点的父节点 
			st.pop();
		}
		if (cur->left != NULL) {
			cur->left->color = black;
			if (cur != root) {
				if (p->left == cur) p->left = cur->left;
				else p->right = cur->left;
			}	
			else root = cur->left;
			delete cur;
			return true;
		}
		else if (cur->right != NULL){
			cur->right->color = black;
			if (cur != root) {
				if (p->left == cur) p->left = cur->right;
				else p->right = cur->right;
			}	
			else root = cur->right;
			delete cur;
			return true;
		}
		/*待删节点是叶节点*/
		else if (cur->color == red){
			if (p->left == cur) p->left = NULL;
			else p->right = NULL;
			delete cur;
			return true; 
		} 
		/*待删的节点是黑色的叶节点,
		注意根到待删节点的完整路径已经存在st中, 
		并且路径包含根和这个代替节点*/
			/*黑色节点,需要考虑的情况比较多。注意如果待删节点是黑色,那么他一定有兄弟,不然也不满足黑色平衡
			同时他兄弟有子节点也只可能是红色的!!!不可能有黑色子节点!!因为他自己是叶节点,这样会破坏平衡性*/
		else {
			RBNode<K, E> *pDel = cur, *ppDel = p;
			while (true) {
				//cout << "ASD" << endl;
				//cout << st.size();
				brother = (p->left == cur) ? p->right : p->left;
				RBNode<K, E> *orgp = p;
				if (cur->color == red || cur == root) {
					if (pDel == ppDel->left) ppDel->left = NULL;
					else pDel->right = NULL;
					delete pDel;
					return true;
				}
				//cout << "ASDsd" << endl;
				if (cur == p->left) {			
					if (brother->color == red) { //兄弟节点是红的,由于红黑树平衡性要求,兄弟节点必有两个黑色子节点,而且父节点是黑色 
						p->color = red;
						brother->color = black;
						brother = brother->left; //为了可以经过情况四的处理 
						RotateL(p);
						if (st.empty()) root = p;
						else {
							RBNode<K, E> *pp = st.top();
							if (pp->left == orgp) pp->left = p;
							else pp->right = p;
						}
						p = p->left;//新的双亲 
					}//再经过一次情况四的处理即可结束 
					else if (brother->color == black) {
						//cout << "brother == black" << endl;
						if (brother->right != NULL && brother->right->color == red) {
							swap(brother->color, p->color);
							brother->right->color = black;
							RotateL(p);
							if (st.empty()) root = p;
							else {
								RBNode<K, E> *pp = st.top();
								if (pp->left == orgp) pp->left = p;
								else pp->right = p;
							}
							break;
						}
						else if ((brother->right == NULL || brother->right->color == black) && 
							(brother->left != NULL && brother->left->color == red)) {
							swap(brother->color, brother->left->color);
							RotateR(brother);
							p->right = brother;
						}//再经过一次情况二处理即可 
						/*左旋一次,直接删除,结束*/

						else if ((brother->right == NULL || brother->right->color == black) && ( 
							brother->left == NULL || brother->left->color == black)) {
							//cout << "double NULL" << endl;
							if (brother->color == black) { 
								brother->color = red;
								cur = p;
							} 
							if (!st.empty()) {
								p = st.top();	
								st.pop();
							}
						}
					}
				}
				else {
					if (brother->color == red) { //兄弟节点是红的,由于红黑树平衡性要求,兄弟节点必有两个黑色子节点,而且父节点是黑色 
						p->color = red;
						brother->color = black;
						brother = brother->right; //为了可以经过情况四的处理 
						RotateR(p);
						if (st.empty()) root = p;
						else {
							RBNode<K, E> *pp = st.top();
							if (pp->left == orgp) pp->left = p;
							else pp->right = p;
						}
						p = p->right;//新的双亲 
					}//再经过一次情况四的处理即可结束 
					else if (brother->color == black) {
						//cout << "brother == black" << endl;
						if (brother->left != NULL && brother->left->color == red) {
							swap(brother->color, p->color);
							brother->left->color = black;
							RotateR(p);
							if (st.empty()) root = p;
							else {
								RBNode<K, E> *pp = st.top();
								if (pp->left == orgp) pp->left = p;
								else pp->right = p;
							}
							break;
						}
						else if ((brother->left == NULL || brother->left->color == black) && 
							(brother->right != NULL && brother->right->color == red)) {
							swap(brother->color, brother->right->color);
							RotateR(brother);
							p->left = brother;
						}//再经过一次情况二处理即可 
						/*左旋一次,直接删除,结束*/

						else if ((brother->right == NULL || brother->right->color == black) && ( 
							brother->left == NULL || brother->left->color == black)) {
							//cout << "double NULL" << endl;
							if (brother->color == black) { 
								brother->color = red;
								cur = p;
							} 
							if (!st.empty()) {
								p = st.top();	
								st.pop();
							}
						}
					}
				}
			}
			if (cur == ppDel->left) ppDel->left = NULL;
			else ppDel->right = NULL;
			cur->color = black;
			delete pDel;
			return true;
		}
	}
	void delete_tree(RBNode<K, E> *ptr) {
		if (ptr != NULL) {
			delete_tree(ptr->left);
			delete_tree(ptr->right);
			delete ptr;
		}
	}
	void preOrder(RBNode<K, E> *ptr) {
		if (ptr != NULL) {
			cout << ptr->data << " color" << ptr->color << endl;
			preOrder(ptr->left);
			preOrder(ptr->right);
		}
	}
	void inOrder(RBNode<K, E> *ptr) {
		if (ptr != NULL) {
			inOrder(ptr->left);
			cout << ptr->data << " color" << ptr->color << endl;
			inOrder(ptr->right);
		}
	}
	void testRBTree(RBNode<K, E> *ptr, int &deep) {
		if (ptr != NULL) {
			if (ptr->color == black) {
				++deep;
			}
			testRBTree(ptr->left, deep);
			testRBTree(ptr->right, deep);
			if (ptr->color == black) --deep;
		}
		else {
			cout << deep << endl;
		}
	}
	
public:
	RBTree(): root(NULL), _size(0) {}
	~RBTree() {
		delete_tree(root);
		root = NULL;
	}
	size_t size() {
		return _size;
	}
	E & Search(K k) {//这个Search实际上是为了Map写的,如果查不到,就插入该节点,这是STL map使用[]访问时的行为 !! 
		bool found = false;
		E &result = Search(root, k, found);
		if (found == false) {
			Insert(E(), k);
			return Search(root, k, found);
		}
		return result;
	}
	bool Contains(K k) {
		bool found = false;
		Search(root, k, found);
		return found;
	}
	bool Insert(E d, K k) {
		return Insert(root, d, k);
	}
	bool Remove(K k) {
		return Remove(root, k);
	}
	void showInOrder() {
		inOrder(root);
	}
	void showPreOrder(){
		preOrder(root);
	}
	void testRB() {
		int deep = 0;
		testRBTree(root, deep);
	}
};

附简易Map代码

#include <iostream>
#include "RBTree.h"
using namespace std;

template <class K, class E>
class Map {
	RBTree<K, E> tree;
public:
	Map() {}
	size_t size() {
		return tree.size();
	}
	bool empty() {
		return tree.size() == 0;
	}
	
	E & operator[](K i) {
		return tree.Search(i);
	}
	bool contains(K k) {
		return tree.Contains(k);
	} 
};
发布了4 篇原创文章 · 获赞 2 · 访问量 124

猜你喜欢

转载自blog.csdn.net/qq_41026469/article/details/104319344