紅黑樹爲何必須掌握?

來看看,紅黑樹的廣泛的應用

  • JDK 1.8開始,HashMap也引入了紅黑樹:當衝突的鏈表長度超過8時,自動轉爲紅黑樹
  • Java中,TreeMap、TreeSet都使用紅黑樹作爲底層數據結構
  • Linux底層的CFS進程調度算法中,vruntime使用紅黑樹進行存儲。
  • 多路複用技術的Epoll,其核心結構是紅黑樹 + 雙向鏈表。

面試過程中,HashMap 常常是面試的重點, 而且會以連環炮 的方式進行發問,

所以, 紅黑樹基本是 面試必須的 要點, 如果 答不上來,面試就有 很大程度 就黃了

紅黑樹,又比較複雜,有非常多的場景, 大家記住不容易。

本文,尼恩幫大家做了 徹底,形象的梳理, 幫助大家 輕鬆 記住 紅黑樹

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

本文的介紹次序

本文,從 BST二叉查找樹, 到AVL 平衡二叉樹, 再到 RBT 紅黑樹,

爲大家 做好 清晰的場景分析, 幫助大家記憶。

BST二叉查找樹

什麼是二叉查找樹呢?

二叉查找樹(BST)具備以下特性:

  1. 左子樹上所有結點的值均小於或等於它的根結點的值。
  2. 右子樹上所有結點的值均大於或等於它的根結點的值。
  3. 左、右子樹也分別爲二叉排序樹。

二叉搜索樹 BST的完美情況

一般人們理解的二叉樹(又叫二叉搜索樹 BST)會出現一個問題,完美的情況下,它是這樣的:

img

二叉搜索樹的查找流程

如何查找值爲7的節點?
1.查看根節點8,因爲7<8,所以再查看它的左子節點6
2.查看左子節點6,因爲7>6,所以再查看它的右子節點7
3.查看右子節點7,因爲7=7,所以就找到啦,

二叉搜索樹的極端情況

二叉查找樹是有缺點的,在不斷插入的時候,有可能出現這樣一種情況:很容易“退化”成鏈表,

如果bst 樹的節點正好從大到小的插入,此時樹的結構也類似於鏈表結構,這時候的查詢或寫入耗時與鏈表相同。

退化成爲了 鏈表的特殊BST

一顆特殊BST,退化成爲了 鏈表,如下圖:

img

它和鏈表一樣,搜索的時候,最壞情況的時間複雜度O(n) 。

那麼我們怎麼避免這種情況呢?

爲了避免這種特殊的情況發生,引入了平衡二叉樹(AVL)和紅黑樹(red-black tree)。

AVL 、rbt 都是通過本身的建樹原則來控制樹的層數和節點位置,

因爲rbtree是由AVL演變而來,所以我們從瞭解AVL開始。

AVL平衡二叉樹

平衡二叉樹也叫AVL(發明者名字簡寫),也屬於二叉搜索樹的一種,與其不同的是AVL通過機制保證其自身的平衡。

AVL樹是最先發明的自平衡二叉查找樹。

在AVL樹中任何節點的兩個子樹的高度最大差別爲1,所以它也被稱爲高度平衡樹。

增加和刪除可能需要通過一次或多次樹旋轉來重新平衡這個樹。

AVL樹的特性

AVL樹本質上還是一棵二叉搜索樹,它有以下特性:

  • 特性1: 對於任何一顆子樹的root根結點而言,它的左子樹任何節點的key一定比root小,而右子樹任何節點的key 一定比root大;

  • 特性2:對於AVL樹而言,其中任何子樹仍然是AVL樹;

  • 特性3:每個節點的左右子節點的高度之差的絕對值最多爲1;

特性1表明,AVL 繼承於 BST , 所以:

1.AVL本身首先是一棵BST 二叉搜索樹。
2.AVL帶有平衡條件:每個結點的左右子樹的高度之差的絕對值(平衡因子)最多爲1。

在插入、刪除樹節點的時候,如果破壞了以上的原則,AVL樹會自動進行調整使得以上三條原則仍然成立。

也就是說,AVL樹,本質上是帶了平衡功能的二叉查找樹(二叉排序樹,二叉搜索樹)。

AVL樹的平衡功能

舉個例子,下左圖爲AVL樹最長的2節點與最短的8節點高度差爲1;

當插入一個新的節點後,根據上面第一條原則,它會出現在2節點的左子樹,但這樣一來就違反了原則3。

img

此時AVL樹會通過節點的旋轉進行進行平衡,

AVL調整的過程稱之爲左旋和右旋,

AVL平衡的調整過程

旋轉之前,首先確定旋轉支點(pivot): 這個旋轉支點就是失去平衡這部分樹,在自平衡之後的根節點,

平衡的調整過程,需要根據pivot它來進行旋轉。

我們在學習AVL樹的旋轉時,不要將失衡問題擴大到整個樹來看,這樣會擾亂你的思路,

我們只關注失衡子樹的根結點 及它的子節點和孫子節點即可。

事實上,AVL樹的旋轉,我們權且叫“AVL旋轉”是有規律可循的,因爲只要聚焦到失衡子樹,然後進行左旋、右旋即可。

很多人在左旋和右旋有時候弄不明白,

其實左旋就是逆時針轉,右旋是順時針轉

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

AVL子樹失衡的四大場景

導致AVL失衡的場景就是有限的4個:

  • 左左結構失衡(LL型失衡)

  • 右右結構失衡(RR型失衡)

  • 左右結構失衡(LR型失衡)

  • 右左結構失衡(RL型失衡)

刪除元素,也會導致AVL失衡,需要再平衡,但是原理和插入元素是類似的。

這裏聚焦 介紹插入元素的平衡過程, 刪除元素,不做介紹。

場景1: LL型失衡-左左結構失衡(右旋):

場景: 插入的元素在子樹root的左側不平衡元素的左側

此時,以root的左兒爲支點,也就是,左側的不平衡元素爲pivot(支點), 進行右旋

在這裏插入圖片描述

來一個右旋的動畫:

在這裏插入圖片描述

右旋過程中,如果pivot有右子樹,則作爲 原root的 左子樹, 保障AVL的特性1

記憶要點

尼恩備註記憶要點,LL型失衡怎麼 平衡呢?

旋轉的反向,與失衡的方向相反,

LL 型失衡,與左邊 相反的方向, 是右邊,所以是右旋

場景2 RR型失衡:右右結構失衡(左旋)

場景:插入的元素在子樹root右側的不平衡子樹的右側

此時,以root的右兒爲支點,也就是,右側的不平衡元素 爲 pivot(支點), 進行左旋

img

來一個左旋的動畫:

在這裏插入圖片描述

左旋過程中,如果pivot有左子樹,則作爲 原root的 右子樹,

保障AVL的特性1,

記憶要點

尼恩備註記憶要點,RR型失衡怎麼 平衡呢?

旋轉的反向,與失衡的方向相反

RR 型失衡,與右邊 相反的方向, 是左邊,所以是左旋

場景3 LR型失衡:左右結構失衡(左旋+右旋):

場景: 插入的元素在左側的不平衡元素的右側

img

記憶要點

尼恩備註記憶要點,LR型失衡怎麼 平衡呢?

旋轉的反向,與失衡的方向相反

LR型失衡,與只相反的方向是 RL,但是先旋轉底部,再旋轉頂部,RL進行次序顛倒,LR

所以, LR型失衡,旋轉的方式,是先左旋, 再右旋

場景4 RL失衡: 右左結構 (右旋+左旋):

場景: 插入的元素在右側的不平衡元素的左側

img

記憶要點

尼恩備註記憶要點,RL型失衡怎麼 平衡呢?

旋轉的反向,與失衡的方向相反

RL型失衡,與只相反的方向是 LR,但是先旋轉底部,再旋轉頂部,所以,LR進行次序顛倒,RL

最終, RL型失衡,旋轉的方式,是先右旋, 再左旋

AVL樹平衡總結

可見無論哪種情況的失衡,都可以通過旋轉來調整。

不難看出,旋轉在圖上像是將pivot(支點)節點向上提(將它提升爲root節點),而後兩邊的節點會物理的分佈在新root節點的兩邊,

接下來按照AVL二叉樹的要求:

左子樹小於root,右子樹大於root進行調整。

從圖LL結構可以看出,當右旋時原來pivot(7)的右子樹(8)會轉變到原root點(9)的左子樹處;

img

從圖右右結構可見,當左旋時,原來pivot(18)的左子樹會分佈到原root點(9)的右子樹。

img

對於左右結構和右左結構無非是經過多次旋轉達到穩定,旋轉的方式並沒有區別,

AVL樹本質上還是一棵二叉搜索樹,它有以下特性:
1.本身首先是一棵二叉搜索樹。
2.帶有平衡條件:每個結點的左右子樹的高度之差的絕對值(平衡因子)最多爲1。

也就是說,AVL樹,本質上是帶了平衡功能的二叉查找樹(二叉排序樹,二叉搜索樹)。

AVL樹的刪除

刪除的判斷標準

  1. 要刪除的節點是什麼類型的節點?;
  2. 刪除後是否會破壞平衡 ;

節點類型

  1. 葉子節點;
  2. 節點只有左子樹或只有右子樹 ;
  3. 既有左右子樹都有。

處理的思路

  1. 當刪除爲葉子節點,則直接刪除,並從父親節點開始往上看,判斷是否失衡;如果沒有失衡,再判斷父親的父節點是否失衡,直到根節點。若失衡則判斷失衡類型(LL、LR、RR、RL),再進行相應的調整。
  2. 刪除的節點只有左子樹或只有右子樹,那麼將節點刪除,以左子樹或右子樹進行代替,並進行相應的平衡判斷,若失衡則調整,一直到根節點 ;
  3. 刪除的節點既有左子樹又有右子樹,找到其前驅或者後驅節點將其替換,再判斷是否失衡,然後根據失衡情況調整,直到根節點。

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

常見AVL面試題

問:什麼是AVL左旋和右旋?

加入節點後,左旋和右旋 ,維護AVL平衡性

右旋轉

場景: 插入的元素在不平衡元素的左側的左側

x.right = y

y.left = xxx(原x.right)

   對節點y進行向右旋轉操作,返回旋轉後新的根節點x
            y                             x
           / \                          /   \
          x   T4     向右旋轉 (y)        z     y
         / \       - - - - - - - ->    / \   / \
        z   T3                       T1  T2 T3 T4
       / \
     T1   T2

場景:插入的元素在不平衡元素的右側的右側

// 向左旋轉過程

x.left = y;

y.right =(原x.left )

對節點y進行向左旋轉操作,返回旋轉後新的根節點x
        y                             x
      /  \                          /   \
     T1   x      向左旋轉 (y)       y     z
         / \   - - - - - - - ->   / \   / \
       T2  z                     T1 T2 T3 T4
          / \
         T3 T4

AVL樹的問題

既然AVL樹可以保證二叉樹的平衡,這就意味着AVL搜索的時候,它最壞情況的時間複雜度O(logn) ,要低於普通二叉樹BST和鏈表的最壞情況O(n)。

那麼HashMap直接使用AVL樹來替換鏈表就好了,爲什麼選擇用紅黑樹呢?

原因是:

由於AVL樹必須保證左右子樹平衡,Max(最大樹高-最小樹高) <= 1,

所以在插入的時候很容易出現不平衡的情況,一旦這樣,就需要進行旋轉以求達到平衡。

正是由於這種嚴格的平衡條件,導致AVL需要花大量時間在調整上,故AVL樹一般使用場景在於查詢場景, 而不是 增加刪除 頻繁的場景。

紅黑樹(rbt)做了什麼優化呢?

紅黑樹(rbt)繼承了AVL可自平衡的優點,

同時, 紅黑樹(rbt)在查詢速率和平衡調整中尋找平衡,放寬了樹的平衡條件,從而可以用於 增加刪除 頻繁的場景。

在實際應用中,紅黑樹的使用要多得多。

紅黑樹(RBTree)

紅黑樹是一種特化的AVL樹(平衡二叉樹)

紅黑樹是在1972年由Rudolf Bayer發明的,當時被稱爲平衡二叉B樹(symmetric binary B-trees).

在1978年被 Leo J. Guibas 和 Robert Sedgewick 修改爲如今的“紅黑樹”.

什麼是紅黑樹?

紅黑樹也是一種自平衡二叉查找樹,它與AVL樹類似,都在添加和刪除的時候通過旋轉操作保持二叉樹的平衡,以求更高效的查詢性能。

與AVL樹相比,紅黑樹犧牲了部分平衡性,以換取插入/刪除操作時較少的旋轉操作,整體來說性能要優於AVL樹。

雖然RBTree是複雜的, 但它的最壞情況運行時間也是非常良好的,並且在實踐中是高效的:

它可以在O(log n)時間內做查找,插入和刪除,這裏的n 是樹中元素的數目.

紅黑樹的特性

紅黑樹是實際應用中最常用的平衡二叉查找樹,它不嚴格的具有平衡屬性,但平均的使用性能非常良好。

在紅黑樹中,節點被標記爲紅色和黑色兩種顏色。

紅黑樹的原則有以下幾點:

  • 特性1:節點非黑即紅

  • 特性2:根節點一定是黑色

  • 特性3:葉子節點(NIL)一定是黑色

  • 特性4:每個紅色節點的兩個子節點都爲黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

  • 特性5:從任一節點到其每個葉子的所有路徑,都包含相同數目的黑色節點。

紅色屬性 說明,紅色節點的孩子,一定是黑色。 但是,RBTree 黑色節點的孩子,可以是紅色,也可以是黑色,具體如下圖。

葉子屬性 說明, 葉子節點可以是空nil ,AVL的葉子節點不是空的,具體如下圖。

img

基於上面的原則,我們一般在插入紅黑樹節點的時候,會將這個節點設置爲紅色,

原因參照最後一條原則: 紅色破壞原則的可能性最小,如果是黑色, 很可能導致這條支路的黑色節點比其它支路的要多1,破壞了平衡。

記憶要點:

可以按照括號裏邊的分類,記住 紅黑樹的幾個原則:

  • 顏色屬性)性質1:節點非黑即紅

  • 根屬性)性質2:根節點一定是黑色

  • 葉子屬性)性質3:葉子節點(NIL)一定是黑色

  • 紅色屬性)性質4:每個紅色節點的兩個子節點,都爲黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

  • (黑色屬性)性質5:從任一節點到其每個葉子的所有路徑,都包含相同數目的黑色節點。

黑色屬性,可以理解爲平衡特徵, 如果滿足不了平衡特徵,就要進行平衡操作。

空間換時間

RBT有點屬於一種空間換時間類型的優化,

在avl的節點上,增加了 顏色屬性的 數據,相當於 增加了空間的消耗。 通過顏色屬性的增加, 換取,後面平衡操作的次數 減少。

黑色完美平衡

紅黑樹並不是一顆AVL平衡二叉搜索樹,從圖上可以看到,根節點P的左子樹顯然比右子樹高

根據 紅黑樹的特性5,從任一節點到其每個葉子的所有路徑,都包含相同數目的黑色節點, 說明:

rbt 的 左子樹和右子樹的黑節點的層數是相等的

紅黑樹的平衡條件,不是以整體的高度來約束的,而是以黑色 節點的 高度,來約束的。

所以稱紅黑樹這種平衡爲黑色完美平衡

在這裏插入圖片描述

看看黑色完美平衡的效果,

去掉 rbt中的紅色節點,會得到 一個四叉樹, 從根節點到每一個葉子,高度相同,就是rbt的root到葉子的黑色路徑長度。

在這裏插入圖片描述

紅黑樹的恢復平衡過程的三個操作

一旦紅黑樹5個原則有不滿足的情況,我們視爲平衡被打破,如何 恢復平衡?

靠它的三種操作:變色、左旋、右旋

1.變色

節點的顏色由紅變黑或由黑變紅。(這個操作很好了解)

2.左旋

以某個結點作爲支點(pivot),其父節點(子樹的root)旋轉爲自己的左子樹(左旋),pivot的原左子樹變成 原root節點的 右子樹,pivot的原右子樹保持不變。

在這裏插入圖片描述

img

3.右旋:

以某個結點作爲支點(pivot),其父節點(子樹的root)旋轉爲自己的右子樹(右旋),pivot的原右子樹變成 原root節點的 左子樹,pivot的原左子樹保持不變。

在這裏插入圖片描述

在這裏插入圖片描述

紅黑樹的左旋、右旋操作,AVL樹的左旋,右旋操作 差不多

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

紅黑樹插入節點情景分析

紅黑樹的節點結構

先看看紅黑樹的節點結構

以HashMap中的紅黑樹的結構定義爲例子:

  static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;
        }


/**
 * Nodes for use in TreeBins
 */
static final class TreeNode<K,V> extends Node<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;

    TreeNode(int hash, K key, V val, Node<K,V> next,
             TreeNode<K,V> parent) {
        super(hash, key, val, next);
        this.parent = parent;
    }

默認新插入的節點爲紅色:

因爲父節點爲黑色的概率較大,插入新節點爲紅色,可以避免顏色衝突

場景1:紅黑樹爲空樹

直接把插入結點作爲根節點就可以了

另外:根據紅黑樹性質 2根節點是黑色的。還需要把插入節點設置爲黑色。

場景2:插入節點的Key已經存在

更新當前節點的值,爲插入節點的值。

在這裏插入圖片描述

情景3:插入節點的父節點爲黑色

由於插入的節點是紅色的,當插入節點的父節點是黑色時,不會影響紅黑樹的平衡,

所以: 直接插入無需做自平衡

在這裏插入圖片描述

情景4:插入節點的父節點爲紅色

根據性質2:根節點是黑色。

如果插入節點的父節點爲紅色節點,那麼該父節點不可能爲根節點,所以插入節點總是存在祖父節點(三代關係)。

根據性質4:每個紅色節點的兩個子節點一定是黑色的。不能有兩個紅色節點相連

此時會出現兩種狀態:

  • 父親和叔叔爲紅色

  • 父親爲紅色,叔叔爲黑色

如圖

在這裏插入圖片描述

場景4.1:父親和叔叔爲紅色節點

根據性質4:紅色節點不能相連 ==》祖父節點肯定爲黑色節點:

父親爲紅色,那麼此時該插入子樹的紅黑樹層數的情況是:黑紅紅。

因爲不可能同時存在兩個相連的紅色節點,需要進行 變色, 顯然處理方式是把其改爲:紅黑紅

變色 處理:黑紅紅 ==> 紅黑紅

1.將F和V節點改爲黑色

2.將P改爲紅色

3.將P設置爲當前節點,進行後續處理

在這裏插入圖片描述

可以看到,將P設置爲紅色了,

如果P的父節點是黑色,那麼無需做處理;

但如果P的父節點是紅色,則違反紅黑樹性質了,所以需要將P設置爲當前節點,繼續插入操作, 作自平衡處理,直到整體平衡爲止。

場景4.2:叔叔爲黑色,父親爲紅色,並且插在父親的左節點

分爲兩種情況

  • LL 紅色插入

叔叔爲黑色,或者不存在(NIL)也是黑節點,並且節點的父親節點是祖父節點的左子節點

注意:單純從插入來看,叔叔節點非紅即黑(NIL節點),否則破壞了紅黑樹性質5,此時路徑會比其他路徑多一個黑色節點。

在這裏插入圖片描述

場景4.2.1 LL型失衡

細分場景 1: 新插入節點,爲其父節點的左子節點(LL紅色情況), 插入後 就是LL 型失衡

在這裏插入圖片描述

自平衡處理:

1.變顏色:

將F設置爲黑色,將P設置爲紅色

2.對F節點進行右旋

在這裏插入圖片描述

場景4.2.2 LR型失衡

細分場景 2: 新插入節點,爲其父節點的右子節點(LR紅色情況), 插入後 就是LR 型失衡

在這裏插入圖片描述

自平衡處理:

1.對F進行左旋

2.將F設置爲當前節點,得到LL紅色情況

3.按照LL紅色情況處理(1.變色 2.右旋P節點)
在這裏插入圖片描述

情景4.3:叔叔爲黑節點,父親爲紅色,並且父親節點是祖父節點的右子節點

在這裏插入圖片描述

情景4.3.1:RR型失衡

新插入節點,爲其父節點的右子節點(RR紅色情況)

在這裏插入圖片描述

自平衡處理:

1.變色:

將F設置爲黑色,將P設置爲紅色

2.對P節點進行左旋

在這裏插入圖片描述

情景4.3.2:RL型失衡

新插入節點,爲其父節點的左子節點(RL紅色情況)

在這裏插入圖片描述

自平衡處理:

1.對F進行右旋

2.將F設置爲當前節點,得到RR紅色情況

3.按照RR紅色情況處理(1.變色 2.左旋 P節點)

在這裏插入圖片描述

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

RBT面試題:

問:有了二叉搜索樹,爲什麼還需要平衡二叉樹?

二叉搜索樹容易退化成一條鏈

這時,查找的時間複雜度從O ( log n)也將退化成O ( N )

引入對左右子樹高度差有限制的平衡二叉樹 AVL,保證查找操作的最壞時間複雜度也爲O ( log n)

問:有了平衡二叉樹,爲什麼還需要紅黑樹?

AVL的左右子樹高度差不能超過1,每次進行插入/刪除操作時,幾乎都需要通過旋轉操作保持平衡

在頻繁進行插入/刪除的場景中,頻繁的旋轉操作使得AVL的性能大打折扣

紅黑樹通過犧牲嚴格的平衡,換取插入/刪除時少量的旋轉操作,

整體性能優於AVL

  • 紅黑樹插入時的不平衡,不超過兩次旋轉就可以解決;刪除時的不平衡,不超過三次旋轉就能解決

  • 紅黑樹的紅黑規則,保證最壞的情況下,也能在O ( log n)時間內完成查找操作。

問:紅黑樹那幾個原則,你還記得麼?

可以按照括號裏邊的分類,記住 紅黑樹的幾個原則:

  • 顏色屬性)節點非黑即紅

  • 根屬性)根節點一定是黑色

  • 葉子屬性)葉子節點(NIL)一定是黑色

  • 紅色屬性)每個紅色節點的兩個子節點,都爲黑色。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點)

  • (黑色屬性)從任一節點到其每個葉子的所有路徑,都包含相同數目的黑色節點。

問:紅黑樹寫入操作 ,是如何找到它的父節點的?

紅黑樹的節點 TreeNode它就是繼承Node結構,

先看看紅黑樹的節點結構

以HashMap中的紅黑樹的結構定義爲例子:

  static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        volatile V val;
        volatile Node<K,V> next;
        }


/**
 * Nodes for use in TreeBins
 */
static final class TreeNode<K,V> extends Node<K,V> {
    TreeNode<K,V> parent;  // red-black tree links
    TreeNode<K,V> left;
    TreeNode<K,V> right;
    TreeNode<K,V> prev;    // needed to unlink next upon deletion
    boolean red;

    TreeNode(int hash, K key, V val, Node<K,V> next,
             TreeNode<K,V> parent) {
        super(hash, key, val, next);
        this.parent = parent;
    }

TreeNode在Node基礎上加了幾個字段,分別指向父節點parent,然後指向左子節點left,還有指向右子節點的right,

然後還有表示顏色red屬性

紅黑樹的插入操作:

首先是找到一個合適的插入點,就是找到插入節點的父節點,

由於紅黑樹 它又滿足BST二叉查找樹的 有序特性,這個找父節點的操作和二叉查找樹是完全一致的。

二叉查找樹,左子節點小於當前節點,右子節點大於當前節點,

然後每一次向下查找一層就可以排除掉一半的數據,查找的效率在log(N)

最終查找到nil節點或者 key一樣的節點。

如果最終查找到 key一樣的節點,進行更新操作。這個TreeNode.key 與當前 put.key 完全一致。這就不需要插入,替換value就可以了,父節點就是當前節點的父節點

如果最終查找到nil節點,進行插入操作。nil節點的父節點,就是當前節點的父節點,把插入的節點替換nil節點。然後進行紅黑樹的 平衡處理。

問:紅黑樹的有那些內部操作

變色

把一個紅色的節點變成黑色,或者把一個黑色的節點變成紅色,就是對這個節點的變色

旋轉

與平衡二叉樹的旋轉操作類似。

紅黑樹與AVL樹區別

1、調整平衡的實現機制不同

紅黑樹根據路徑上黑色節點數目一致,來確定是否失衡,如果失衡,就通過變色和旋轉來恢復

AVL根據樹的平衡因子(所有節點的左右子樹高度差的絕對值不超過1),來確定是否失衡,如果失衡,就通過旋轉來恢復

2、紅黑樹的插入效率更高

紅黑樹是用非嚴格的平衡來換取增刪節點時候旋轉次數的降低,任何不平衡都會在三次旋轉之內解決

紅黑樹並不追求“完全平衡”,它只要求部分地達到平衡要求,降低了對旋轉的要求,從而提高了性能

而AVL是嚴格平衡樹(高度平衡的二叉搜索樹),因此在增加或者刪除節點的時候,根據不同情況,旋轉的次數比紅黑樹要多。

所以紅黑樹的插入效率更高

3、紅黑樹統計性能比AVL樹更高

紅黑樹能夠以O(log n) 的時間複雜度進行查詢、插入、刪除操作。

AVL樹查找、插入和刪除在平均和最壞情況下都是O(log n)

紅黑樹的算法時間複雜度和AVL相同,但統計性能比AVL樹更高

4、適用性:AVL查找效率高

如果你的應用中,查詢的次數遠遠大於插入和刪除,那麼選擇AVL樹,如果查詢和插入刪除次數幾乎差不多,應選擇紅黑樹

即,有時僅爲了排序(建立-遍歷-刪除),不查找或查找次數很少,R-B樹合算一些。

說明:本文會以pdf格式持續更新,更多最新尼恩3高pdf筆記,請從下面的鏈接獲取:語雀 或者 碼雲

參考文獻:

https://blog.csdn.net/longsq602/article/details/114165028
https://www.jianshu.com/p/d7024b52858c
https://juejin.cn/post/6844903877188272142
https://blog.csdn.net/qq_50227688/article/details/114301326
https://blog.csdn.net/qq116165600/article/details/103361385
https://blog.csdn.net/falling_stars_/article/details/115574847
https://blog.csdn.net/u014454538/article/details/120120216
https://blog.csdn.net/u014454538/article/details/120120216
https://blog.csdn.net/jiang_wang01/article/details/113715033
https://baijiahao.baidu.com/s?id=1680540960651232140&wfr=spider&for=pc
https://www.jianshu.com/p/e136ec79235c
https://www.cnblogs.com/LiaHon/p/11203229.html
http://www.ty2y.com/study/hhszphgc.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章