從上學期就一直打算寫出紅黑樹,可是因爲能力太水,插入操做始終沒法看明白,最近學習數據結構從新將紅黑樹的插入操做看了一遍,結合《算法導論》,《data structures and programing design in C++》 和侯捷的《STL源碼》,終於弄清楚插入操做中保持樹結構的幾種狀況,雖然這三本書在分類上有些許的差異,但本質的方法仍是同樣的。ios
我仍是根據算法導論將其分爲3種狀況(STL是分爲4種狀況):算法
首先必須明白的狀況是:每次插入節點的都設爲紅條件,若是須要保持紅黑樹結構時,則必然是新增節點的父親節點也是紅色,並且祖父節點必須是黑色(由於未插入前是一棵符合要求的紅黑樹)數據結構
1.叔父節點爲紅色---處理:將父親節點和叔父節點同時設爲黑色,祖父節點設爲紅色,此時必須考慮祖父節學習
點的父親節點是否爲黑色,因此將指針而後向上移動兩層,繼續往上判斷是否知足紅黑樹性質。spa
2. 叔父節點爲黑色且是外側插入----處理:進行單旋轉操做,單旋轉操做與AVL樹相似,可是在細節處理上指針
須要格外注意,由於RB_Node有指向父節點的parent指針;code
3. 叔父節點爲黑色且是內測插入----處理: 進行雙旋轉操做,旋轉後更改兩個節點顏色便可,雙旋轉操做blog
其實能夠分解爲左右兩次單旋轉操做,因此算法導論中這種狀況ci
是隻進行單旋轉操做轉化爲狀況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 }