Java代碼實現紅黑樹

目錄:

  1. 紅黑樹的特性
    1. 節點不是紅色就是黑色
    2. 根節點爲黑色
    3. 葉子節點爲黑色
    4. 每個紅色節點其子節點必須是黑色節點。
    5. 任意節點到到其任意的子節點的所有路徑的黑色節點的數量相等
  2. 紅黑樹維持其特性的方法:變色和旋轉
  3. 算法
    1. 插入
    2. 刪除

 

一.紅黑樹維持其特性的方法:變色和旋轉

  1. 紅黑樹的基本操作包括刪除和添加。在刪除或者添加一個節點的時候就有可能打破原有的紅黑樹維持的平衡,那麼就需要通過變色和旋轉的方式來使紅黑樹重新達到平衡。着色是非常簡單的,直接將節點的顏色改變就可以了,多以要理解紅黑樹,就必須需要懂得如何進行旋轉,旋轉又分爲左旋和右轉,兩個操作相反的,所以理解了一個旋轉的操作就很容易理解另一個旋轉了。

    1. 左旋

       

      如圖所示,紅色節點爲旋轉支點,支點往左子樹移動即爲左旋。左旋之後我們可以看到原支點的位置被原支點的右子節點代替,新支點的左子節點變爲了原來爲父節點的原支點,新支點的左子節點變爲原支點的右子節點,因此左旋操作總共右3個節點,以爲旋轉前的結構舉例,分別爲紅色節點(原支點),黃色節點(新支點)和L節點。

    2. 右旋

      右旋操作和左旋相反的,兩者互反。依然是紅色作爲旋轉支點,右旋後黃色節點代替了紅色節點原來的位置,黃色節點的右節點旋轉後變爲紅色節點的左節點 。

 

二.插入操作

插入操作步驟:(自底向上插入)

  1. 將新結點設置爲紅色插入到紅黑樹中
    這裏爲什麼需要設置成紅色呢?主要是爲了滿足特性5,這樣在插入節點後就少解決了一個衝突,也就少一點麻煩。插入完成後,我們來看一下還有那些特性是有可能發生衝突的,特性1每個節點不是紅色就是黑色的,這明顯沒有衝突,特性2根節點爲黑色,當插入節點爲根節點的時候就會有衝突了,這種就很簡單了,直接將根節點着色爲黑色即可。特性3每個葉子節點都是黑色,這個明顯沒有衝突。特性4每個紅色節點的子節點都是黑色的,這個特性就有可能會衝突,因爲在插入新節點的時候我們無法確定新節點的父節點的顏色是黑色的還是紅色,如果新節點的父節爲黑色,那麼就不會有衝突,否則就會違背了特性4。特性5任意節點,到其任意子節點的所有路徑都包含相同的黑色節點,因爲我們插入的新節點被着色爲紅色,所以並不會影響到每個路徑的黑色節點的數量,因此也不會有衝突。綜上所訴,那麼在插入新節點的時候,只有特性4有可能發生衝突。
  2. 判斷新插入的結點的父結點的顏色
    1. 如果新插入的結點的父結點是黑色,那麼插入結束。
    2. 如果新插入的結點的父結點是紅色,則分爲兩種情況處理:
      1. 若其父結點的兄弟結點是黑色,則分爲兩種情況處理:
        1. 情況1:新節點爲左節點,解決:p和g右旋,並且p變黑色,g變紅色。還有它們的子結點的轉移,下同
        2. 情況2:新節點爲右節點,解決:p和n先左旋(和情況1相同了),再n和p右旋,並且n變黑色,g變紅色。
      2. 若其父結點的兄弟結點是紅色,則分爲兩種情況處理:
        1. 情況3:新節點爲左節點
        2. 情況4:新節點爲右節點

          上面兩種情況解決方法:
          1. 只需要將祖父結點變爲紅色節點,父結點和其兄弟結點變爲黑色即可
          2. 但是這只是樹的局部的平衡,這裏又要分兩種情況了
            1. 如果g的父結點是一個黑色,那麼插入結束
            2. 如果g的父結點也是一個紅結點呢

              這裏又分爲兩種情況處理:
              1. g結點的父結點的兄弟結點是紅色
                這種情況是不是相當於【如果新插入的結點的父結點是紅色,若其父結點的兄弟結點是紅色】
                解決方法:只需要將祖父結點變爲紅色節點,父結點和其兄弟結點變爲黑色,然後一層一層的往上平衡就可以了(方法嵌套調用),當祖父節點爲根結點的時候,我們直接將根節點着色爲黑色即可,因爲祖父節點的兩個子節點都是黑色的,所以變爲黑色後仍然是平衡的
              2. g結點的父結點的兄弟結點是黑色
                是不是就上面討論的【如果新插入的結點的父結點是紅色,若其父結點的兄弟結點是黑色】
                解決方法:按照上面討論的解決方法解決。
                插入n結點的兩次維持紅黑樹過程:

 

 

三.刪除操作

二叉排序樹刪除一個節點的時候有以下3種情況:

  1. 刪除的節點沒有子節點
  2. 刪除的節點只有一個子節點
  3. 刪除的節點有兩個子節點

紅黑樹也以此分析

  1. 情況一:刪除的節點沒有子節點
    1. 直接刪除
  2. 情況二:刪除的節點只有一個子節點
    1. 如果其是紅色,直接刪除,然後用其子結點替代
    2. 如果其是黑色
      1. 第一種情況:如果其兄弟結點是紅色
        將兄弟節點設爲黑色,父節點設爲紅色,以父節點爲支點左旋轉,然後將父節點的右節點放到兄弟節點上
      2. 第二種情況:兄弟節點是黑色的
        1. A.兄弟的兩個子節點也都是黑色的
          解決:兄弟節點設爲紅色,把父節點設置爲新的刪除節點
        2. B.兄弟節點的左子節點是紅色,右子節點是黑色
          解決:將兄弟節點的左子節點設爲黑色,兄弟節點設爲紅色,以兄弟節點爲支點右旋,把父節點的右節點設置爲兄弟節點
        3. C.兄弟節點的右子節點是紅色,左子節點任意顏色
          解決:把兄弟節點的設爲父節點的顏色,父節點設爲黑色,父節點的右節點設爲黑色,父節點爲支點左旋
  3. 情況三:刪除的節點有兩個子節點
    1. 如果其是紅色,則首先找該節點的替換節點(即右子樹中最小的節點,因爲其其沒有左孩子結點,替換方便),接着替換要刪除的節點爲替換節點,然後刪除替換節點。如果替換結點是黑色,則改爲紅色。
    2. 如果其是黑色
      1. 第一種情況:如果其兄弟結點是紅色
        將兄弟節點設爲黑色,父節點設爲紅色,以父節點爲支點左旋轉,然後將父節點的右節點放到兄弟節點上
      2. 第二種情況:兄弟節點是黑色的
        1. A.兄弟的兩個子節點也都是黑色的
          解決:兄弟節點設爲紅色,把父節點設置爲新的刪除節點
        2. B.兄弟節點的左子節點是紅色,右子節點是黑色
          解決:將兄弟節點的左子節點設爲黑色,兄弟節點設爲紅色,以兄弟節點爲支點右旋,把父節點的右節點設置爲兄弟節點
        3. C.兄弟節點的右子節點是紅色,左子節點任意顏色
          解決:把兄弟節點的設爲父節點的顏色,父節點設爲黑色,父節點的右節點設爲黑色,父節點爲支點左旋

圖解說一下第二種情況

  1. 如果N結點是紅色,直接刪除,結束
  2. 如果N結點是黑色
    1. 第一種情況:如果其兄弟結點是紅色
      將兄弟節點設爲黑色,父節點設爲紅色,以父節點爲支點左旋轉,然後將父節點的右節點放到兄弟節點上
    2. 第二種情況:兄弟節點是黑色的
      1. A.兄弟的兩個子節點也都是黑色的
        解決:兄弟節點設爲紅色,把父節點設置爲新的刪除節點
      2. B.兄弟節點的左子節點是紅色,右子節點是黑色
        解決:將兄弟節點的左子節點設爲黑色,兄弟節點設爲紅色,以兄弟節點爲支點右旋,把父節點的右節點設置爲兄弟節點
      3. C.兄弟節點的右子節點是紅色,左子節點任意顏色
        解決:把兄弟節點的設爲父節點的顏色,父節點設爲黑色,父節點的右節點設爲黑色,父節點爲支點左旋
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章