前幾天學習epoll函式,發現epoll函式使用紅黑樹結構儲存epfd來提高fd檢索速度,又想起hashmap中引入了紅黑樹在達到一定鍊錶長度後轉為紅黑樹來避免鍊錶遍歷。
紅黑樹的應用這麼廣泛,我們應該對其有所了解。
首先我們應該知道,在無序線性表中查詢是否存在某個值需要對線性表進行遍歷,其查詢時間複雜度為on,但如果線性表是有序的,使用二分法查詢,其時間複雜度就會降低為ologn,讓待查詢的線性表保持有序顯然是有利於查詢操作的,但這種便利並不是沒有代價的,不論是各種排序演算法,還是在構建線性表時就保持有序,都會帶來額外的操作,例如mysqlnnodb使用的多路查詢平衡b+樹,又或者是我們最熟悉的平衡二叉樹,其維護有序的成本都很高,而紅黑樹,想必大家早就有所耳聞或有所了解,接下來我們詳細介紹這種排序樹好在**,本篇純屬個人理解原創,做交流記錄用,僅供參考。
什麼是紅黑樹,紅黑樹的要求有哪些,本文不再贅述,網上找到的文章都有答案,了解到紅黑樹的結構和條件後,會發現,與二叉平衡樹非常相似,只是平衡的條件和要求不同,這也是我一直以來的疑惑,二叉平衡樹的邏輯很好理解,通過旋轉來達到平衡條件,使得最大查詢長度為logn,那為什麼epoll和hashmap不直接使用**l樹呢?我認為最終要的原因就是**l的平衡條件太苛刻,左右子樹的高度差不能超過1,否則就要出發複雜的rebalance操作,從實際使用的角度來看,在n較大的情況下logn和logn + 1的查詢效率差別不大,反而因為苛刻條件而導致的開銷不能功過相抵,在寫操作頻繁的操作中,**l似乎並不能很好的適應,換句話說,**l樹太完美了,也太敏感了。
相信大家和我有一樣的疑惑,紅黑樹的那些平衡條件是怎麼總結出來的,似乎並不是**l這種順應邏輯的條件,更像是推導出來的條件,因此,我們從rbt的近親--2-3樹說起。
2-3樹,大家也有所耳聞,2-3樹存在三種節點,第一種是2-節點,資料域有乙個值,指標域有兩個值;第二種是3-節點,資料域有2個值,指標域有3個值;還有一種是空節點,如下圖所示:
2-3樹的插入和構建過程如下圖所示,可參考:介紹的很詳細
可以知道的是,2-3樹在插入過程中不斷增長出新的根,使得樹的高度不斷增高,底層節點高度永遠相等,忽略2節點和3節點的差異後會發現這是一顆完全二叉樹,
所有節點的高度都相等,是一顆完美的**l樹
如果我們把當前節點同父節點之間的邊的顏色計作節點的顏色,則會變成下圖所示:
這就是這顆2-3樹唯一對應的rbt,由上圖展開前的情況可知,未展開紅色節點前,所有節點的高度完全一致,展開紅色節點後,忽略掉紅色節點,所有節點的黑高就是完全一致的,
這就是紅黑二叉樹的性質之一:所有節點的黑高一致。
由展開過程和分配節點顏色可知只有父節點原來是3節點時,才會將乙個父節點中的乙個染色為紅色,但是展開後,該紅色父節點變成了2節點,不會對該節點進行展開操作,所以該節點的子節點一定是黑色,
這就是紅黑樹的第二條性質:不會存在連續的兩個紅色節點,或者說,紅色節點的子節點必為黑色節點。
根據這些性質,保證了展開後的紅黑樹的最長查詢路徑不會超過最短路徑的2倍,同時沒有**l樹那麼敏感,像上圖插入10號節點後已經不滿足**l的定義需要調整了,在操作節點頻繁的情況下,rbt帶來的開銷要比**l小。
如果是查多操作少的情況,則**l樹的穩定性更好。
由2 3樹到紅黑樹 紅黑樹的巨集觀架構之構造2 3樹
希望看此文前了解什麼是2 3樹,就不介紹什麼是2 3樹了 查詢遍歷也不說了 直接上難啃的骨頭 2 3樹中節點插入規則 規則1 優先搜尋並沉底 規則2 沉底產生4節點則分解 規則一很容易理解,即向2節點插入新節點key k 產生3節點,若以前2節點的key是k,產生左子樹 如果不小心最後面節點是3節點...
紅黑樹筆記 紅黑樹的插入操作
紅黑樹的插入操作可以在o logn 的時間內完成。開始插入節點的時候和二叉查詢樹一樣,只需要最後將插入的節點著成紅色,為了保證紅黑樹的性質,需要通過rb insertfixup函式來調整該節點,對其重新著色並旋轉。下面先呼叫rb insert 函式將乙個節點插入到紅黑樹中,同樣先上偽 rb inse...
紅黑樹下 紅黑樹的實現
1.實現紅黑樹的基本思想 實際上,紅黑樹是有固定的平衡過程的 遇到什麼樣的節點分布,我們就對應怎麼去調整。只要按照這些固定的調整規則來操作,就能將乙個非平衡的紅黑樹調整成平衡的。首先,我們需要再來看一下紅黑樹的定義 在插入 刪除節點的過程中,第 三 四點要求可能會被破壞,所以 平衡調整 實際上就是把...