算法導論 - 紅黑樹及紅黑樹平衡的詳細解析個人理解

算法導論 - 紅黑樹及紅黑樹平衡的詳細解析個人理解

紅黑樹一種數據結構,效率極高,插入和刪除的操作的時間複雜度都是logn,雖然紅黑樹對於前端來說基本很少用到,但是作爲一個目標是全棧的程序員來說,算法的學習是很必要的,so … 圖是"借的",字都是自己打的,也依據了自己的理解

數組 鏈表

數組特點是元素在內存中緊挨着存儲,因而優點是定位快(O(1)),缺點是插入刪除慢(O(n));而鏈表則不同,它通過指針將不同位置的元素鏈接起來,因而優缺點與數組正好相反:定位慢(O(n)),插入刪除快(O(1))

排序二叉樹

紅黑樹是特殊的排序二叉樹,所以這裏我們先介紹一下排序二叉樹, 二叉樹相較於二叉樹具有以下特性,二叉樹內的節點是不能重複的

  • 一個節點下只最多隻有兩個子節點

  • 節點的左子樹都小於根節點的值

  • 節點的右子樹都大於根節點的值
    在這裏插入圖片描述

排序二叉樹的時間複雜度在完全平衡情況下爲O(lgN),在極端情況下二叉樹的時間複雜度爲O(N),等於順序排列的時間複雜度, 所以二叉樹的時間複雜度在O(lgN)和O(N)之間,所以我們希望能構造一個比較平衡的二叉樹, 這樣效率比較穩定
在這裏插入圖片描述

二叉樹的平衡與不平衡與插入的順序有關

紅黑樹性質(R-B Tree)

HashMap, TreeMap, TreeSet

  1. 每節點都是紅色或黑色

  2. 根節點是黑色

  3. 每個葉子節點(就是最末端的節點也就是null)是黑色(一般畫圖省略null)

  4. 如果一個節點是紅色,那麼它的兩個子節點都是黑色(也就是說不能有兩個相鄰的紅色節點)

  5. 從任一 節點開始到其所有子孫葉結點的路徑中所包含的黑色結點數量必須相同。

在這裏插入圖片描述

紅黑樹 - 黑色高度

這裏要闡明一個概念,從根節點到葉節點的包含的黑色節點的數量(不包括根節點)就是棵樹的黑色高度, 例如上面這棵樹的黑色高度就是

由此可知, 紅黑樹的任一節點到其葉節點的路徑最長路徑不超過最短路徑的兩倍,這就是相當於使用近似的平衡

簡單的來說,就是能夠保證二叉樹的的每條分支的長度差不多

那如何保證的呢?!!

這裏我們先來看一個圖

在這裏插入圖片描述

可以發現同樣的數據,可以用兩種不同的二叉樹來表示, 而這種操作就是紅黑樹用來平衡二叉樹的方式 ,即左旋/右旋 , 當然還有變色

什麼是左旋和右旋 (這裏先說如何操作,再說什麼時候使用)

在這裏插入圖片描述

左旋

在這裏插入圖片描述

右旋

因爲相同元素的二叉樹不是一個固定的結構,所每個節點都可以對他進行左旋右旋的操作,這樣操作之後仍舊能保持二叉樹的性質, 而紅黑樹讓我們在插入和刪除的過程中爲了保證紅黑的性質, 做左旋右旋或者變色的調整,從而保持紅黑樹的平衡

那麼在插入和刪除時我們是如何調整的呢!

插入

在插入之前,我們首先規定插入的節點顏色都爲紅色 ,因爲(從任一 節點開始到其所有子孫葉結點的路徑中所包含的黑色結點數量必須相同)這條規定,如果我們插入了黑色節點很容易就破壞了規定

下面我們想一下,在插入一個紅色節點的時候會發生哪些情況,我們一一分析

  1. 插入的節點的位置爲根節點, 直接塗黑就行了,根節點爲黑色

  2. 插入位置父節點是一個黑色節點,顯然這種情況我們不需要調整

  3. 插入的位置父節點是一個紅色節點, 這時候就需要調整了,以爲兩個紅色連在一起會違背規定4 ,這裏分成三種情況

    • 插入位置爲左鍵點, 父節點爲紅 , 叔叔節點爲黑/nil的情況, 這是只需要進行一次左旋/右旋,然後將父節點變黑, 原來的爺爺節點變紅,保證黑色數量不變

在這裏插入圖片描述

  • 插入位置爲右鍵點, 父節點爲紅 , 叔叔節點爲黑/nil的情況, 因爲本節點比父節點大, 父節點作爲子節點的左節點 ,這樣和上面的情況就一樣了不做贅述了

在這裏插入圖片描述

  • 父節點爲紅 , 叔叔節點爲紅,這時候爺爺節點必是黑,這時候很簡單直接把父親和叔叔變黑,爺爺節點變紅就行了,這時候萬一爺爺的爸爸也是紅怎麼辦, 這時候我們就把爺爺節點當做一個新插入的節點做同樣操作就行了

在這裏插入圖片描述

刪除

一個節點前驅後繼

在瞭解刪除之前,我們首先需要知道的的是一個節點的前驅和後繼是什麼 , 簡單來說就是離這個節點數字最近的兩個數字節點

在這裏插入圖片描述

這裏舉個例子,以17爲例子,他的前驅就是16後驅就是19

這時我們需要刪除17這個節點,就可以把他的前驅或者後繼放到他的位置上來位置二叉樹結構, 這樣就相當於我們只是刪除了前驅(後繼)上的節點, 這有什麼用呢,因爲前驅和後繼的情況比較簡單,前驅只能有左節點,後繼只能有右節點,當前驅和後繼被當成替死鬼之後, 子節點直接被當成備胎提來

這裏爲了方便解釋,我們將刪除後新生成的樹的各個角色標記

  • N就是那個備胎
  • P是父節點
  • S是兄弟節點
  • SL是左侄子節點
  • SR是右侄子節點
  • X沒有標記就是被刪除的節點,原來在N的位置
    在這裏插入圖片描述

這裏我們也將刪除分成幾種情況

  • 被刪除的節點是紅色, 不需要平衡不影響黑色數量

  • N節點爲紅色,只要直接變成紅色就好了

  • 被刪除的節點是黑色,N也是黑色(下面可以分爲這幾種)

    1. 所有節點都爲黑色

在這裏插入圖片描述

 **操作:  直接將S變成紅色,這時P節點下的整個樹都比其他分支少一個黑色節點,這時我們把P看成一個新的N節點來處理,向上重新來平衡樹**

在這裏插入圖片描述

  1. P節點爲紅, 其他都爲黑

在這裏插入圖片描述

 **操作: 將P變成黑,S變成紅, 這時經過S的分支數量沒有變化, N這邊剛好多了一個平衡了**

在這裏插入圖片描述

  1. 節點和SL節點顏色不重要, N,S爲黑, SR爲紅

在這裏插入圖片描述

 **操作: 以P左旋,P和S顏色互換,SR改爲黑色,經過N的多了一個P, 經過SL的不變,SR因爲自己變黑了所以也不變**

在這裏插入圖片描述

  1. P節點顏色不重要,SL爲紅,SR爲黑,因爲上面的以及討論過SR爲紅的情況了

在這裏插入圖片描述

 **操作: 以S節點右旋轉,交換S和SL顏色, 這樣的旋轉不會改變S各分支的黑色數量,這時由於SL原來是紅色,所以他的左子節點必定是黑色, 所以我們可以發現這種情況與上面的情況4相同,按照上面的方法來平衡**

在這裏插入圖片描述

  1. S節點事紅色,其他節點都是黑色

在這裏插入圖片描述

 **操作: 以P爲點,左旋轉, 交換P和S的顏色, 這是N所處的情況就是P爲紅,兄弟爲黑的情況了,可以參照2,3,4具體情況處理**

在這裏插入圖片描述

到這裏所以平衡的情況都處理完了!!!

總結

​ 總的來說紅黑樹就是通過旋轉變色,來維持整個紅黑二叉樹的平衡,最終保證不管添加了多少各節點, 最長分支不會超過最短分支的兩倍長度,這樣能保證每次操作的效率都是比較穩定的 .

​ 但是這種樹並不是非常平衡,當然還存在一種AVL樹, 是一種完全平衡樹, 分支之間節點數量不能差超過一個節點,但是這樣勢必會增加平衡的操作,得不償失. 紅黑樹的插入平衡次數最多兩次, 刪除最多平衡三次 , AVl樹插入刪除的複雜度都是log(N),但是在查詢是效率是要高於紅黑樹的

​ 說了這麼多紅黑樹的平衡,其實講道理基本看的時候理解了,到這裏忽然有失憶了,我覺得學習紅黑樹並不是要背下來是如何處理的,是要去了解平衡過程中的思路,順帶膜拜膜拜大佬們的思想,到底是怎麼想出這個東西的!

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