从上学期就一直打算写出红黑树,但是由于能力太水,插入操作始终无法看明白,最近学习数据结构重新将红黑树的插入操作看了一遍,结合《算法导论》,《data structures and programing design in C++》 和侯捷的《STL源码》,终于弄清楚插入操作中保持树结构的几种情况,虽然这三本书在分类上有些许的差别,但本质的方法还是一样的。
我还是根据算法导论将其分为3种情况(STL是分为4种情况):
首先必须明白的情况是:每次插入节点的都设为红条件,如果需要保持红黑树结构时,则必然是新增节点的父亲节点也是红色,而且祖父节点必须是黑色(因为未插入前是一棵符合要求的红黑树)
1.叔父节点为红色---处理:将父亲节点和叔父节点同时设为黑色,祖父节点设为红色,此时必须考虑祖父节
点的父亲节点是否为黑色,所以将指针然后向上移动两层,继续往上判断是否满足红黑树性质。
2. 叔父节点为黑色且是外侧插入----处理:进行单旋转操作,单旋转操作与AVL树类似,但是在细节处理上
需要格外注意,因为RB_Node有指向父节点的parent指针;
3. 叔父节点为黑色且是内测插入----处理: 进行双旋转操作,旋转后更改两个节点颜色即可,双旋转操作
其实可以分解为左右两次单旋转操作,所以算法导论中这种情况
是只进行单旋转操作转化为情况2,我这里将其合并。
删除操作比较复杂,,有时间再看。。贴上自己写的插入代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 enum Color {red, black}; 6 template<class Record> 7 //树节点 8 struct RB_Node{ 9 Color color; 10 Record data; 11 RB_Node *left, *right, *parent; 12 RB_Node() {left = right = parent = NULL; color = red;} 13 RB_Node(RB_Node*subroot, Record& data_) { 14 left = right = NULL; 15 parent = subroot; 16 color = red; data = data_; 17 } 18 }; 19 20 template<class Record> 21 class RB_Tree { 22 public: 23 RB_Tree() {root == NULL;} 24 bool insert(Record& data_); 25 void Inorder(); 26 private: 27 void fix_up(RB_Node<Record>* &T, RB_Node<Record>* &z); 28 void Left_Rotate(RB_Node<Record>* &T, RB_Node<Record>* &x); 29 void Right_Rotate(RB_Node<Record>* &T, RB_Node<Record>* &x); 30 void recursive_inorder(RB_Node<Record>* subroot); 31 RB_Node<Record>* root; 32 }; 33 34 template<class Record> 35 bool RB_Tree<Record>::insert(Record& data_) { 36 //插入新元素 37 RB_Node<Record> *x = root, *y = NULL; 38 while (x) { 39 y = x; 40 if ((x->data) > data_) x = x->left; 41 else x = x->right; 42 } 43 RB_Node<Record>* z = new RB_Node<Record>(y, data_); 44 if (y == NULL) { 45 root = z; root->color = black; return true; 46 } else if (data_ < y->data) { 47 y->left = z; 48 } else { 49 y->right = z; 50 } 51 fix_up(root, z); //保持树结构 52 return true; 53 } 54 template<class Record> 55 void RB_Tree<Record>::fix_up(RB_Node<Record>* &T, RB_Node<Record>* &z) { 56 while (z->parent && (z->parent)->color == red) { 57 if ((z->parent)->parent->left == z->parent) { //父亲节点位于祖父节点的左侧 58 RB_Node<Record>* y = (z->parent)->parent->right; 59 if (y && y->color == red) { //case 1: 叔父节点为红色节点(注意若为nil是黑色节点) 60 y->color = black; 61 z->parent->color = black; 62 (z->parent)->parent->color = red; 63 z = (z->parent)->parent; 64 } else { 65 if (z == z->parent->right) { //case 2: 叔父节点为黑色且节点为内侧插入 66 z = z->parent; 67 Left_Rotate(T, z); 68 } 69 (z->parent)->color = black; //case 3:叔父节点为黑色且节点为外侧插入 70 (z->parent)->parent->color = red; 71 z = (z->parent)->parent; 72 Right_Rotate(T, z); 73 } 74 } else { //父亲节点位于祖父节点右侧,与上面类似 75 RB_Node<Record>* y = (z->parent)->parent->left; 76 if (y && y->color == red) { 77 y->color = black; 78 z->parent->color = black; 79 (z->parent)->parent->color = red; 80 z = (z->parent)->parent; 81 } else { 82 if (z == (z->parent)->left) { 83 z = z->parent; 84 Right_Rotate(T, z); 85 } 86 (z->parent)->color = black; 87 ((z->parent)->parent)->color = red; 88 z = (z->parent)->parent; 89 Left_Rotate(T, z); 90 } 91 } 92 } 93 if (z->parent == NULL) z->color = black; 94 } 95 template<class Record> //旋转操作时应特别注意NULL的情况,需要考虑三对关系:1.x与y->left 2.x->parent 与y 3. x与y 96 void RB_Tree<Record>::Left_Rotate(RB_Node<Record>* &T, RB_Node<Record>* &x) { 97 RB_Node<Record>* y = x->right; 98 x->right = y->left; 99 if (y->left != NULL) (y->left)->parent = x; 100 y->parent = x->parent; 101 if (x->parent == NULL) { 102 T = y; 103 } else if ((x->parent)->right == x){ 104 (x->parent)->right = y; 105 } else { 106 (x->parent)->left = y; 107 } 108 y->left = x; 109 x->parent = y; 110 } 111 template<class Record> //The same as Left_rotate 112 void RB_Tree<Record>::Right_Rotate(RB_Node<Record>* &T, RB_Node<Record>* &x) { 113 RB_Node<Record>* y = x->left; 114 x->left = y->right; 115 if (y->right != NULL) (y->right)->parent = x; 116 y->parent = x->parent; 117 if (x->parent == NULL) { 118 T = y; 119 } else if ((x->parent)->right == x) { 120 (x->parent)->right = y; 121 } else { 122 (x->parent)->left = y; 123 } 124 y->right = x; 125 x->parent = y; 126 } 127 128 //test inorder_traversal 129 template<class Record> 130 void RB_Tree<Record>::Inorder() { 131 recursive_inorder(root); 132 } 133 template<class Record> 134 void RB_Tree<Record>::recursive_inorder(RB_Node<Record>* subroot) { 135 if (subroot != NULL) { 136 recursive_inorder(subroot->left); 137 cout << subroot->data << endl; 138 recursive_inorder(subroot->right); 139 } 140 } 141 142 int main() { 143 RB_Tree<int> rb; 144 for (int i = 0; i < 10; i++) { 145 int u; 146 cin >> u; 147 rb.insert(u); 148 rb.Inorder(); 149 cout << endl; 150 } 151 // rb.Inorder(); 152 return 0; 153 }