红黑树类算法实现

来源:互联网 发布:渝中男性医院网络预约 编辑:程序博客网 时间:2024/06/06 01:31

继续参考Wiki(http://zh.wikipedia.org/wiki/%E7%BA%A2%E9%BB%91%E6%A0%91),资料如下:

性质

红黑树是每个节点都带有颜色属性的二叉查找树,颜色为红色黑色。在二叉查找树强制一般要求以外,对于任何有效的红黑树我们增加了如下的额外要求:

性质1. 节点是红色或黑色。

性质2. 根是黑色。

性质3. 所有叶子都是黑色(叶子是NIL节点)。

性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

性质5. 从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。


简单实现代码如下:

/*红黑树目标实现红黑树的平衡操作主要是参考平衡根的兄弟或者叔父节点的颜色来判断的,主要是性质黑色节点数一样的平衡。Author:BetaBinDate:2012.04.30*/#include <iostream>#include <cstdio>using namespace std;//节点颜色值#define BLACK 0#define RED 1//红黑树节点结构template<class ValueType>struct RbNode {ValueType data;int color;RbNode<ValueType> *left;RbNode<ValueType> *right;RbNode<ValueType> *parent;//一般用于NIL节点创建,颜色默认为黑色RbNode(){color = BLACK;}//一般用于新节点创建,颜色默认为红色RbNode(ValueType value){color = RED;data = value;}};//红黑树模板类//实现简单的中序遍历输出、插入、删除操作//辅助的插入平衡、删除平衡、左旋、右旋template<class ValueType>class RbTree{public:RbTree();~RbTree();void InfixOutput(RbNode<ValueType>* node);//中序遍历输出结果,用作测试void InsertData(ValueType value);//插入新数据,重复会被忽视,既是不插入void EraseData(ValueType value);//删除数据RbNode<ValueType> *root;//树根节点指针RbNode<ValueType> *NIL;//树NIL哨兵节点指针private:RbNode<ValueType>* FindValue(ValueType value);//寻找对应值的节点RbNode<ValueType>* InfixSuccessor(RbNode<ValueType>* node);//寻找中序遍历后继,无后继则返回NILvoid LeftRotate(RbNode<ValueType>* node);//左旋void RightRotate(RbNode<ValueType>* node);//右旋void DestroyTree(RbNode<ValueType>* root);//销毁以root为根的树void InsertBalance(RbNode<ValueType>* node);//插入平衡操作void EraseBalance(RbNode<ValueType>* node);//删除平衡操作};template<class ValueType>RbTree<ValueType>::RbTree(){//创建哨兵NIL = new RbNode<ValueType>();root = NIL;}template<class ValueType>RbTree<ValueType>::~RbTree(){//销毁树节点内存和哨兵if (NIL != root){DestroyTree(root);}delete NIL;}template<class ValueType>void RbTree<ValueType>::DestroyTree(RbNode<ValueType>* treeRoot){if (NIL != treeRoot->left){DestroyTree(treeRoot->left);}if (NIL != treeRoot->right){DestroyTree(treeRoot->right);}delete treeRoot;}//寻找中序遍历后继template<class ValueType>RbNode<ValueType>* RbTree<ValueType>::InfixSuccessor(RbNode<ValueType>* node){if (NIL == node->right){//后继在祖宗处RbNode<ValueType>* parent = node->parent;while (parent != NIL && node == parent->right){parent = node;node = node->parent;}}else{//节点有右子树情况下,递归至最左节点node = node->right;while (NIL != node->left){node = node->left;}}return node;}//中序遍历输出,用作测试template<class ValueType>void RbTree<ValueType>::InfixOutput(RbNode<ValueType>* node){if (NIL != node){InfixOutput(node->left);cout << node->data << endl;InfixOutput(node->right);}}//左旋:\旋转变为/理解template<class ValueType>void RbTree<ValueType>::LeftRotate(RbNode<ValueType>* node){//先改变x和y子树转移RbNode<ValueType>* temp = node->right;node->right = temp->left;if (NIL != temp->left){temp->left->parent = node;}//完成x和y父亲转移temp->parent = node->parent;if (NIL == node->parent){root = temp;}else if (node == node->parent->left){node->parent->left = temp;} else{node->parent->right = temp;}//完成x和y两者之间关系转移temp->left = node;node->parent = temp;}//右旋:/旋转变为\理解template<class ValueType>void RbTree<ValueType>::RightRotate(RbNode<ValueType>* node){//先完成x和y子树转移RbNode<ValueType>* temp = node->left;node->left = temp->right;if (NIL != temp->right){node->left->parent = node;}//完成x和y父亲转移temp->parent = node->parent;if (NIL == node->parent){root = temp;}else if (node->parent->left == node)//不小心删掉一个等号,愣是找了N久错误,勿先入为主{node->parent->left = temp;} else{node->parent->right = temp;}//完成x和y之间转移temp->right = node;node->parent = temp;}//寻找值template<class ValueType>RbNode<ValueType>* RbTree<ValueType>::FindValue(ValueType value){RbNode<ValueType>* scanner = root;while (NIL != scanner){if (value == scanner->data){break;} else if (value < scanner->data){scanner = scanner->left;} else{scanner = scanner->right;}}return scanner;}//插入数据template<class ValueType>void RbTree<ValueType>::InsertData(ValueType value){//已经存在,不需要重复插入if (NIL != FindValue(value)){return ;}RbNode<ValueType> *current = root;RbNode<ValueType> *pre = NIL;RbNode<ValueType> *newNode = new RbNode<ValueType>(value);//找到插入位置:pre子树while (current != NIL){pre = current;if (current->data > value){current = current->left;}else{current = current->right;}}//新节点关系链更新newNode->parent = pre;if (NIL == pre){root = newNode;}else if (value < pre->data){pre->left = newNode;}else{pre->right = newNode;}newNode->left = NIL;newNode->right = NIL;//插入平衡操作InsertBalance(newNode);}//共六种情况,按照对称有三种讨论//1、node的叔叔y是红色的//2、node的叔叔y是黑色的,而且node是右孩子//3、node的叔叔y是黑色的,而且node是左孩子template<class ValueType>void RbTree<ValueType>::InsertBalance(RbNode<ValueType>* node){while (RED == node->parent->color){RbNode<ValueType>* uncle;//父节点为左节点时处理,另一种情况为父节点为右节点if (node->parent == node->parent->parent->left){uncle = node->parent->parent->right;//叔为红节点时,直接颜色转换即可if (RED == uncle->color){node->parent->color = BLACK;uncle->color = BLACK;node->parent->parent->color = RED;}else{//否则先判断是否需要左旋//将位置转为/形状if (node == node->parent->right){node = node->parent;LeftRotate(node);}//颜色重设后直接右旋node->parent->color = BLACK;node->parent->parent->color = RED;RightRotate(node->parent->parent);}}else{//同上三种情况分析,对称处理uncle = node->parent->parent->left;if (RED == uncle->color){node->parent->color = BLACK;uncle->color = BLACK;node->parent->parent->color = RED;}else{if (node == node->parent->left){node = node->parent;RightRotate(node);}node->parent->color = BLACK;node->parent->parent->color = RED;LeftRotate(node->parent->parent);}}}//根节点颜色刷新root->color = BLACK;}//先确定需要删除的节点,可以是自身(不同时有两个子节点的情况下),也可以是一个替换节点。//找到需要删除节点的一个非空子节点(需要删除的节点最多只有一个非空子节点)或空子节点//断开需要删除节点指针,连接其子节点和父节点//再判断是否删除还是替换内容template<class ValueType>void RbTree<ValueType>::EraseData(ValueType value){RbNode<ValueType>* nodetodelete;RbNode<ValueType>* nodetodeletechild;RbNode<ValueType>* target = FindValue(value);//要删除的key不存在if (NIL == target){return ;}//找到要真正要删除的节点if (NIL == target->left || NIL == target->right){nodetodelete = target;}else{nodetodelete = InfixSuccessor(target);}//找到nodetodelete的需要连接子节点if (NIL == nodetodelete->left){nodetodeletechild = nodetodelete->right;} else{nodetodeletechild = nodetodelete->left;}//断开删除节点,连接其父节点与子节点nodetodeletechild->parent = nodetodelete->parent;if (NIL == nodetodelete->parent){root = nodetodeletechild;}else if (nodetodelete == nodetodelete->parent->left){nodetodelete->parent->left = nodetodeletechild;}else{nodetodelete->parent->right = nodetodeletechild;}//需要内容覆盖的情况if (nodetodelete != target){target->data = nodetodelete->data;}//删除节点为黑色的则需要平衡操作if (BLACK == nodetodelete->color){EraseBalance(nodetodeletechild);}delete nodetodelete;}//共八种情况,对称处理四种情况//1、node的兄弟是红色的//2、node的兄弟是黑色的,而且兄弟的两个孩子都是黑色的//3、node的兄弟是黑色的,而且兄弟的左孩子是红色的,右孩子是黑色的//4、node的兄弟是黑色的,而且兄弟的右孩子是红色的template<class ValueType>void RbTree<ValueType>::EraseBalance(RbNode<ValueType>* node){RbNode<ValueType>* brother;while (node != root && BLACK == node->color){if (node == node->parent->left){//兄弟节点变量赋值brother = node->parent->right;//Case1if (RED == brother->color){brother->color = BLACK;node->parent->color = RED;LeftRotate(node->parent);brother = node->parent->right;}//Case2if (BLACK == brother->left->color && BLACK == brother->right->color){brother->color = RED;node = node->parent;}//Case3else if (BLACK == brother->right->color){brother->left->color = BLACK;brother->color = RED;RightRotate(brother);brother = node->parent->right;}//Case4else{brother->color = node->parent->color;node->parent->color = BLACK;brother->right->color = BLACK;LeftRotate(node->parent);node = root;}}else{//兄弟节点变量赋值brother = node->parent->left;//Case1if (RED == brother->color){brother->color = BLACK;node->parent->color = RED;RightRotate(node->parent);brother = node->parent->left;}//Case2if (BLACK == brother->left->color && BLACK == brother->right->color){brother->color = RED;node = node->parent;}//Case3else if (BLACK == brother->left->color){brother->right->color = BLACK;brother->color = RED;LeftRotate(brother);brother = node->parent->left;}//Case4else{brother->color = node->parent->color;node->parent->color = BLACK;brother->left->color = BLACK;RightRotate(node->parent);node = root;}}}node->color = BLACK;}int main(){RbTree<int> test;int selection;int inputdata;do {cout << "Input selection(0:insert;1:erase;2:quit;3:InfixPrint)";cin >> selection;switch (selection){case 0:cout << "Please input the data to insert:";cin >> inputdata;test.InsertData(inputdata);break;case 1:cout << "Please input the data to delete:";cin >> inputdata;test.EraseData(inputdata);break;case 2:break;case 3:test.InfixOutput(test.root);default:;}} while (2 != selection);return 0;}