紅黑樹學習筆記

      從上學期就一直打算寫出紅黑樹,可是因爲能力太水,插入操做始終沒法看明白,最近學習數據結構從新將紅黑樹的插入操做看了一遍,結合《算法導論》,《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 }
相關文章
相關標籤/搜索