亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

STL源碼剖析---紅黑樹原理詳解上

2019-11-10 20:50:37
字體:
來源:轉載
供稿:網友


轉載請標明出處,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7740956

一、紅黑樹概述

     紅黑樹和我們以前學過的AVL樹類似,都是在進行插入和刪除操作時通過特定操作保持二叉查找樹的平衡,從而獲得較高的查找性能。不過自從紅黑樹出來后,AVL樹就被放到了博物館里,據說是紅黑樹有更好的效率,更高的統計性能。這一點在我們了解了紅黑樹的實現原理后,就會有更加深切的體會。     紅黑樹和AVL樹的區別在于它使用顏色來標識結點的高度,它所追求的是局部平衡而不是AVL樹中的非常嚴格的平衡。學過數據結構的人應該都已經領教過AVL樹的復雜,但AVL樹的復雜比起紅黑樹來說簡直是小巫見大巫,紅黑樹才是真正的變態級數據結構。     由于STL中的關聯式容器默認的底層實現都是紅黑樹,因此紅黑樹對于后續學習STL源碼還是很重要的,有必要掌握紅黑樹的實現原理和源碼實現。     紅黑樹是AVL樹的變種,紅黑樹通過一些著色法則確保沒有一條路徑會比其它路徑長出兩倍,因而達到接近平衡的目的。所謂紅黑樹,不僅是一個二叉搜索樹,而且必須滿足一下規則:     1、每個節點不是紅色就是黑色。     2、根節點為黑色。     3、如果節點為紅色,其子節點必須為黑色。     4、任意一個節點到到NULL(樹尾端)的任何路徑,所含之黑色節點數必須相同。上面的這些約束保證了這個樹大致上是平衡的,這也決定了紅黑樹的插入、刪除、查詢等操作是比較快速的。 根據規則4,新增節點必須為紅色;根據規則3,新增節點之父節點必須為黑色。當新增節點根據二叉搜索樹的規則到達其插入點時,卻未能符合上述條件時,就必須調整顏色并旋轉樹形,如下圖:假設我們為上圖分別插入節點3、8、35、75,根據二叉搜索樹的規則,插入這四個節點后,我們會發現它們都破壞了紅黑樹的規則,因此我們必須調整樹形,也就是旋轉樹形并改變節點的顏色。

二、紅黑樹上結點的插入

      在討論紅黑樹的插入操作之前必須要明白,任何一個即將插入的新結點的初始顏色都為紅色。這一點很容易理解,因為插入黑點會增加某條路徑上黑結點的數目,從而導致整棵樹黑高度的不平衡。但如果新結點的父結點為紅色時(如下圖所示),將會違反紅黑樹的性質:一條路徑上不能出現相鄰的兩個紅色結點。這時就需要通過一系列操作來使紅黑樹保持平衡。      為了清楚地表示插入操作以下在結點中使用“新”字表示一個新插入的結點;使用“父”字表示新插入點的父結點;使用“叔”字表示“父”結點的兄弟結點;使用“祖”字表示“父”結點的父結點。插入操作分為以下幾種情況:1、黑父     如下圖所示,如果新節點的父結點為黑色結點,那么插入一個紅點將不會影響紅黑樹的平衡,此時插入操作完成。紅黑樹比AVL樹優秀的地方之一在于黑父的情況比較常見,從而使紅黑樹需要旋轉的幾率相對AVL樹來說會少一些。2、紅父     如果新節點的父結點為紅色,這時就需要進行一系列操作以保證整棵樹紅黑性質。如下圖所示,由于父結點為紅色,此時可以判定,祖父結點必定為黑色。這時需要根據叔父結點的顏色來決定做什么樣的操作。青色結點表示顏色未知。由于有可能需要根結點到新點的路徑上進行多次旋轉操作,而每次進行不平衡判斷的起始點(我們可將其視為新點)都不一樣。所以我們在此使用一個藍色箭頭指向這個起始點,并稱之為判定點。2.1 紅叔當叔父結點為紅色時,如下圖所示,無需進行旋轉操作,只要將父和叔結點變為黑色,將祖父結點變為紅色即可。但由于祖父結點的父結點有可能為紅色,從而違反紅黑樹性質。此時必須將祖父結點作為新的判定點繼續向上(迭代)進行平衡操作。需要注意的是,無論“父節點”在“叔節點”的左邊還是右邊,無論“新節點”是“父節點”的左孩子還是右孩子,它們的操作都是完全一樣的(其實這種情況包括4種,只需調整顏色,不需要旋轉樹形)。2.2 黑叔當叔父結點為黑色時,需要進行旋轉,以下圖示了所有的旋轉可能:Case 1:Case 2:Case 3:

Case 4:

      可以觀察到,當旋轉完成后,新的旋轉根全部為黑色,此時不需要再向上回溯進行平衡操作,插入操作完成。需要注意,上面四張圖的“叔”、“1”、“2”、“3”結點有可能為黑哨兵結點。      其實紅黑樹的插入操作不是很難,甚至比AVL樹的插入操作還更簡單些。紅黑樹的插入操作源代碼如下:[cpp] view plain copy// 元素插入操作  insert_unique()  // 插入新值:節點鍵值不允許重復,若重復則插入無效  // 注意,返回值是個pair,第一個元素是個紅黑樹迭代器,指向新增節點  // 第二個元素表示插入成功與否  template<class Key , class Value , class KeyOfValue , class Compare , class Alloc>  pair<typename rb_tree<Key , Value , KeyOfValue , Compare , Alloc>::iterator , bool>  rb_tree<Key , Value , KeyOfValue , Compare , Alloc>::insert_unique(const Value &v)  {      rb_tree_node* y = header;    // 根節點root的父節點      rb_tree_node* x = root();    // 從根節點開始      bool comp = true;      while(x != 0)      {          y = x;          comp = key_compare(KeyOfValue()(v) , key(x));    // v鍵值小于目前節點之鍵值?          x = comp ? left(x) : right(x);   // 遇“大”則往左,遇“小于或等于”則往右      }      // 離開while循環之后,y所指即插入點之父節點(此時的它必為葉節點)      iterator j = iterator(y);     // 令迭代器j指向插入點之父節點y      if(comp)     // 如果離開while循環時comp為真(表示遇“大”,將插入于左側)      {          if(j == begin())    // 如果插入點之父節點為最左節點              return pair<iterator , bool>(_insert(x , y , z) , true);          else     // 否則(插入點之父節點不為最左節點)              --j;   // 調整j,回頭準備測試      }      if(key_compare(key(j.node) , KeyOfValue()(v) ))          // 新鍵值不與既有節點之鍵值重復,于是以下執行安插操作          return pair<iterator , bool>(_insert(x , y , z) , true);      // 以上,x為新值插入點,y為插入點之父節點,v為新值        // 進行至此,表示新值一定與樹中鍵值重復,那么就不應該插入新值      return pair<iterator , bool>(j , false);  }    // 真正地插入執行程序 _insert()  template<class Key , class Value , class KeyOfValue , class Compare , class Alloc>  typename<Key , Value , KeyOfValue , Compare , Alloc>::_insert(base_ptr x_ , base_ptr y_ , const Value &v)  {      // 參數x_ 為新值插入點,參數y_為插入點之父節點,參數v為新值      link_type x = (link_type) x_;      link_type y = (link_type) y_;      link_type z;        // key_compare 是鍵值大小比較準則。應該會是個function object      if(y == header || x != 0 || key_compare(KeyOfValue()(v) , key(y) ))      {          z = create_node(v);    // 產生一個新節點          left(y) = z;           // 這使得當y即為header時,leftmost() = z          if(y == header)          {              root() = z;              rightmost() = z;          }          else if(y == leftmost())     // 如果y為最左節點              leftmost() = z;          // 維護leftmost(),使它永遠指向最左節點      }      else      {          z = create_node(v);        // 產生一個新節點          right(y) = z;              // 令新節點成為插入點之父節點y的右子節點          if(y == rightmost())              rightmost() = z;       // 維護rightmost(),使它永遠指向最右節點      }      parent(z) = y;      // 設定新節點的父節點      left(z) = 0;        // 設定新節點的左子節點      right(z) = 0;       // 設定新節點的右子節點      // 新節點的顏色將在_rb_tree_rebalance()設定(并調整)      _rb_tree_rebalance(z , header->parent);      // 參數一為新增節點,參數二為根節點root      ++node_count;       // 節點數累加      return iterator(z);  // 返回一個迭代器,指向新增節點  }      // 全局函數  // 重新令樹形平衡(改變顏色及旋轉樹形)  // 參數一為新增節點,參數二為根節點root  inline void _rb_tree_rebalance(_rb_tree_node_base* x , _rb_tree_node_base*& root)  {      x->color = _rb_tree_red;    //新節點必為紅      while(x != root && x->parent->color == _rb_tree_red)    // 父節點為紅      {          if(x->parent == x->parent->parent->left)      // 父節點為祖父節點之左子節點          {              _rb_tree_node_base* y = x->parent->parent->right;    // 令y為伯父節點              if(y && y->color == _rb_tree_red)    // 伯父節點存在,且為紅              {                  x->parent->color = _rb_tree_black;           // 更改父節點為黑色                  y->color = _rb_tree_black;                   // 更改伯父節點為黑色                  x->parent->parent->color = _rb_tree_red;     // 更改祖父節點為紅色                  x = x->parent->parent;              }              else    // 無伯父節點,或伯父節點為黑色              {                  if(x == x->parent->right)   // 如果新節點為父節點之右子節點                  {                      x = x->parent;                      _rb_tree_rotate_left(x , root);    // 第一個參數為左旋點                  }                  x->parent->color = _rb_tree_black;     // 改變顏色                  x->parent->parent->color = _rb_tree_red;                  _rb_tree_rotate_right(x->parent->parent , root);    // 第一個參數為右旋點              }          }          else          // 父節點為祖父節點之右子節點          {              _rb_tree_node_base* y = x->parent->parent->left;    // 令y為伯父節點              if(y && y->color == _rb_tree_red)    // 有伯父節點,且為紅              {                  x->parent->color = _rb_tree_black;           // 更改父節點為黑色                  y->color = _rb_tree_black;                   // 更改伯父節點為黑色                  x->parent->parent->color = _rb_tree_red;     // 更改祖父節點為紅色                  x = x->parent->parent;          // 準備繼續往上層檢查              }              else    // 無伯父節點,或伯父節點為黑色              {                  if(x == x->parent->left)        // 如果新節點為父節點之左子節點                  {                      x = x->parent;                      _rb_tree_rotate_right(x , root);    // 第一個參數為右旋點                  }                  x->parent->color = _rb_tree_black;     // 改變顏色                  x->parent->parent->color = _rb_tree_red;                  _rb_tree_rotate_left(x->parent->parent , root);    // 第一個參數為左旋點              }          }      }//while      root->color = _rb_tree_black;    // 根節點永遠為黑色  }      // 左旋函數  inline void _rb_tree_rotate_left(_rb_tree_node_base* x , _rb_tree_node_base*& root)  {      // x 為旋轉點      _rb_tree_node_base* y = x->right;          // 令y為旋轉點的右子節點      x->right = y->left;      if(y->left != 0)          y->left->parent = x;           // 別忘了回馬槍設定父節點      y->parent = x->parent;        // 令y完全頂替x的地位(必須將x對其父節點的關系完全接收過來)      if(x == root)    // x為根節點          root = y;      else if(x == x->parent->left)         // x為其父節點的左子節點          x->parent->left = y;      else                                  // x為其父節點的右子節點          x->parent->right = y;      y->left = x;      x->parent = y;  }      // 右旋函數  inline void _rb_tree_rotate_right(_rb_tree_node_base* x , _rb_tree_node_base*& root)  {      // x 為旋轉點      _rb_tree_node_base* y = x->left;          // 令y為旋轉點的左子節點      x->left = y->right;      if(y->right != 0)          y->right->parent = x;           // 別忘了回馬槍設定父節點      y->parent = x->parent;        // 令y完全頂替x的地位(必須將x對其父節點的關系完全接收過來)      if(x == root)          root = y;      else if(x == x->parent->right)         // x為其父節點的右子節點          x->parent->right = y;      else                                  // x為其父節點的左子節點          x->parent->left = y;      y->right = x;      x->parent = y;  }  轉載請標明出處,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7740956


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
91精品国产91久久| 国产美女精彩久久| 成人网在线观看| 亚洲免费伊人电影在线观看av| 日韩国产欧美精品一区二区三区| 久久精品成人欧美大片古装| 一区二区三区视频免费在线观看| www高清在线视频日韩欧美| 国产欧美日韩免费| 日本国产欧美一区二区三区| 久久99视频精品| 91精品国产高清| 国产成人一区二区三区小说| 欧美怡红院视频一区二区三区| 中文字幕av一区二区三区谷原希美| 日韩精品在线视频| 欧美尺度大的性做爰视频| 久久精品国亚洲| 日韩精品免费在线视频| 91免费视频国产| 国产色视频一区| 亚洲国语精品自产拍在线观看| 欧美国产一区二区三区| 亚洲第一综合天堂另类专| 日韩av中文字幕在线播放| 中文字幕日韩专区| 日本精品一区二区三区在线播放视频| 欧美影院成年免费版| 精品久久久久久国产| 亚洲人成在线观| 欧美在线观看www| 亚洲欧美中文日韩在线v日本| 91国产精品视频在线| 在线观看日韩视频| 91网站免费观看| 国产精品日韩在线一区| 亚洲一区二区国产| 中文字幕久久亚洲| 亚洲一区美女视频在线观看免费| 国产美女扒开尿口久久久| 欧美激情va永久在线播放| 国内精品国产三级国产在线专| 91成品人片a无限观看| 欧美日韩激情小视频| 亚洲在线一区二区| 亚洲曰本av电影| 欧美国产视频一区二区| 亚洲精品91美女久久久久久久| 福利一区福利二区微拍刺激| 久久精品国产亚洲| 亚洲美女视频网| 国产91精品久久久久久久| 中文字幕欧美日韩精品| 国产三级精品网站| 亚洲黄一区二区| 久久免费精品日本久久中文字幕| 98精品在线视频| 欧美最顶级丰满的aⅴ艳星| 97高清免费视频| 中文字幕亚洲欧美日韩在线不卡| 久久久久免费精品国产| 久久久久www| 一级做a爰片久久毛片美女图片| 亚洲电影免费在线观看| 久久久国产精彩视频美女艺术照福利| 亚洲精品一区二区三区婷婷月| 成人在线视频福利| 欧美在线中文字幕| 亚洲欧美另类中文字幕| 亚洲国产欧美一区二区三区同亚洲| 国产精品久久久久久久久| 欧美一级片一区| 国产91成人在在线播放| 日韩免费在线电影| 欧美久久久精品| 亚洲性生活视频| 5252色成人免费视频| 久久人人爽人人爽人人片亚洲| 欧美精品18videos性欧美| 一区二区三区 在线观看视| 日本久久亚洲电影| 久久久久久91| 91久久国产精品| 亚洲天堂日韩电影| 精品视频久久久久久| 欧美精品在线免费播放| 久久国产精品免费视频| 欧美高清视频在线| 在线播放日韩精品| 久久99热精品这里久久精品| 久久久人成影片一区二区三区观看| 欧美丰满少妇xxxxx做受| 亚洲美腿欧美激情另类| 国产成人精品免高潮费视频| 久久久国产在线视频| 国产亚洲免费的视频看| 国色天香2019中文字幕在线观看| 成人免费看片视频| 91精品国产91久久久| 777777777亚洲妇女| 1769国产精品| 亚洲精品国精品久久99热| 国产小视频国产精品| 人人澡人人澡人人看欧美| 97人人爽人人喊人人模波多| 韩国v欧美v日本v亚洲| 91免费视频网站| 91在线观看免费观看| 午夜精品一区二区三区在线| 国产精品亚洲视频在线观看| 日韩在线视频线视频免费网站| 91精品久久久久久久久久入口| 欧美黄网免费在线观看| 一本色道久久综合亚洲精品小说| 岛国av一区二区在线在线观看| 日韩一级黄色av| 一本色道久久综合狠狠躁篇的优点| 亚洲精品一区在线观看香蕉| 九色精品免费永久在线| 91精品成人久久| 亚洲欧美在线免费观看| 国产一区二区三区视频| 亚洲一级免费视频| 亚洲成人av片在线观看| 国产成人极品视频| 国产精品亚洲аv天堂网| 538国产精品一区二区免费视频| 久久精品一区中文字幕| 97视频网站入口| 国产成人精品一区二区| 美日韩在线视频| 欧美福利视频在线| 日韩av在线一区二区| 精品久久久久久久久久久久| 欧美巨猛xxxx猛交黑人97人| 欧美成人午夜剧场免费观看| 黄色91在线观看| 91亚洲精品一区| 精品无人国产偷自产在线| 日韩成人av一区| 欧美国产精品va在线观看| 欧美福利小视频| 亚洲成人999| 精品成人在线视频| 一区国产精品视频| 精品香蕉在线观看视频一| 91精品国产网站| 日韩av电影在线播放| 国产精品久久久久av免费| 日韩电影在线观看中文字幕| 精品日韩视频在线观看| 国产精品69av| 丝袜美腿精品国产二区| 日韩免费在线观看视频| 岛国av一区二区三区| 欧美激情一区二区三级高清视频| 夜夜躁日日躁狠狠久久88av| 亚洲最大福利网| 欧美裸体视频网站| 国产精品露脸av在线| 亚洲欧洲一区二区三区久久| 亚洲成人av资源网| 日韩精品在线观看网站| 在线性视频日韩欧美|