1. 程式人生 > 實用技巧 >為什麼被減數減去減數等於被減數加上減數的反碼?補數怎麼來的?為什麼用補數?可溢位計數系統

為什麼被減數減去減數等於被減數加上減數的反碼?補數怎麼來的?為什麼用補數?可溢位計數系統

紅黑樹

一、為什麼會出現紅黑樹

因為一棵由n個結點隨機構造的二叉查詢樹的高度為lgn,所以順理成章,二叉查詢樹的一般操作的執行時間為O(lgn)。但二叉查詢樹若退化成了一棵具有n個結點的線性鏈後,則這些操作最壞情況執行時間為O(n)。

於是出現了平衡二叉樹,可以看我之前寫的部落格:

平衡二叉樹保證了在最差的情況下,二叉樹依然能夠保持絕對的平衡,即左右兩個子樹的高度差的絕對值不超過1。但是這又會帶來一個問題,那就是平衡二叉樹的定義過於嚴格,導致每次插入或者刪除一個元素之後,都要去維護二叉樹整體的平衡,這樣產生額外的代價又太大了。二叉搜尋樹可能退化成連結串列,而平衡二叉樹維護平衡的代價開銷又太大了,那怎麼辦呢?這就要談到“中庸之道”的智慧了。說白了就是把平衡的定義適當放寬,不那麼嚴格,這樣二叉樹既不會退化成連結串列,維護平衡的開銷也可以接受。沒錯,這就是我們要談的紅黑樹了。

二、什麼是紅黑樹

紅黑樹是一種含有紅黑結點並能自平衡的二叉查詢樹。它必須除了滿足二叉搜尋樹的性質外,還要滿足下面的性質:

  • 每個節點要麼是黑色,要麼是紅色。
  • 根節點是黑色。
  • 每個葉子節點是黑色。
  • 每個紅色結點的兩個子結點一定都是黑色。
  • 任意一結點到每個葉子結點的路徑都包含數量相同的黑結點。

正是紅黑樹的這5條性質,使一棵n個結點的紅黑樹始終保持了logn的高度,從而也就解釋了上面所說的“紅黑樹的查詢、插入、刪除的時間複雜度最壞為O(log n)”這一結論成立的原因。

三、插入的過程

1、按照搜尋樹的特徵進行插入

2、插入的時候有意識的碰瓷是紅色不能相鄰這個特徵(即插入的為 紅色節點)

3、隨著插入的完成

  • 插入的節點是根節點,把顏色改為黑色
  • 插入的節點的父節點是黑節點,插入完成
  • 插入接節點的父節點為紅色,破壞了紅色節點不能相鄰的原則,需要修復

4、插入完成,結果也是一顆紅黑樹

四、破壞怎麼修復

已知條件:新插入節點(cur)是紅色。cur 的父節點(parent)是紅色

推匯出結論:cur 的祖父節點-- 父親的父親(grandpa)一定是黑色

​ 因為,如果grandpa 為紅色,則parent 和 grandpa 都是紅色,已經不再是紅黑樹了。
在這裡插入圖片描述

1、情況一

1、uncle是存在的,且顏色為紅色,即為下圖:
在這裡插入圖片描述
grandpa + parent/uncle 代表的是兩條路徑,在這兩條路徑上,各自提供了1個黑色

修復規則:任然保證這兩條路徑上只有一個黑色

即:grandpa:黑 -> 紅

​ parent/uncle:紅 -> 黑

然後再考慮 grandpa 和它的父節點問題

cur = grandpa

parent = cur.parent

grandpa = parent.parent

按照同樣的規則進行檢查,直到 根 or 滿足條件

修改後的樣子:

在這裡插入圖片描述

2、情況2

情況2:uncle 不存在或者 uncle 存在,顏色為黑色

情況2.1、cur 是 parent 左邊,並且 parent 是 grandpa 左邊(兩個順邊)

在這裡插入圖片描述
修復方式

對 parent 進行右旋

parent:紅 -> 黑

grandpa:黑 -> 紅
在這裡插入圖片描述
所有路徑只有一個黑色


在這裡插入圖片描述
四條路徑,黑色顏色不一樣多,所以 parent 之前一定右子樹,並且兩邊子樹至少有一層黑色

修復後:
在這裡插入圖片描述

情況2.2、cur 是 parent 右邊,並且 parent 是 grandpa 右邊(兩個順邊)

修復方式

對 parent 進行左旋

parent:紅 -> 黑

grandpa:黑 -> 紅

情況2.3、cur 是 parent 右邊,並且 parent 是 grandpa 左邊(不順邊)

在這裡插入圖片描述
修復方法:

對 parent 進行 右旋

原來的cur 視為 parent

原來的parent 視為 cur

得到如下:
在這裡插入圖片描述
然後再按照2.1處理

情況2.4、cur 是 parent 左邊,並且 parent 是 grandpa 右邊(不順邊)

同2.3


最後,把根節點同一改為 黑色

五、用途

紅黑樹 和 AVL 樹適用範圍是重疊的,都是 二叉平衡搜尋樹,都適合記憶體級別的資料查詢問題

用途:

jdk/c++/linux 中都比較偏向使用紅黑樹

Windows 偏向使用 AVL樹

Java 中使用紅黑樹的地方

1、TreeMap/TreeSet

2、HashMap如果發生衝突太嚴重,用紅黑樹代替連結串列