在學習紅黑樹的時候,看了不少文章,發現都沒有講明白紅黑樹的原理,只是簡單列了紅黑樹的幾條規則,就開始講解紅黑樹的插入,讓人一直不知其因此然。也很難深入的理解紅黑樹。
最後翻起了《算法》這本書,仔細瞭解了二叉樹查找樹、2-3樹、紅黑樹,才明白了紅黑樹不是無緣無故產生的,而是符合科學的發展觀念是按部就班,站在巨人的肩旁上發展起來的。html
這也是咱們從學生時代的填鴨式的學習方式的轉變,不單單是隻學習結論,而且要了解結論產生的歷史及發展。
這樣咱們才能從搬磚、碼農成長爲工程師、科學家。java
一位計算機科學的大牛說過:node
程序 = 數據結構 + 算法
數據結構是爲了減小查詢、刪除的時間複雜度和空間複雜度。git
鏈表的一個節點是由:節點值、節點的下一個節點(字節點)的地址
二叉查找樹一個節點:節點值、節點的左子節點的地址、節點的右子節點的地址
2-3樹:由2節點、3節點組成github
![圖. 2節點 3節點]()算法
2節點:微信
3節點:markdown
紅黑樹(平衡二叉查找樹):節點值、節點的左子節點、節點的右子節點、節點顏色數據結構
二叉查找樹:是由2節點的樹組成的,最壞的時間複雜度是O(N)
插入的幾種狀況:學習
根據以上的四種狀況,咱們能夠看出,若是咱們插入的值是從1開始逐漸遞增的,那麼樹就最終生長得很像鏈表。
private Node<T> root = null;//根節點 private class Node<T>{ public T value;//爲了下面的簡單演示設屬性爲 pubilc public Node<T> left;//真正使用的時候應該爲private 用get、set方法訪問 public Node<T> right; public Node<T> parent; public Node(T value, Node<T> parent) { this.value = value; this.parent = parent; } }
若是查找的值等於根節點的值,那麼查找命中,不然遞歸的在根的子樹中(經過比較與根節點的值選擇左/右節點)查找。
//返回null 樹中沒有此節點 ,遞歸的下左/右子節點查詢 public Node<T> get(T value){ Node<T> node = root; while(true){ if(node == null){ return null; } if(node.value == value){ return node; }else if(node.value > value){ if(node.right == null){ return null; }else if(node.right.value == value){ return node.right; } node = node.right; }else if(node.value < value){ if(node.left == null){ return null; }else if(node.left.value == value){ return node.left; } node = node.left; } } }
插入和查找很像,若是樹的根節點爲空(空樹)則插入到根節點,不然遞歸的在子樹中判斷,當子樹爲null的時候,插入。
public Node<T> put(T value){ Node<T> node = root; while(true){ if(node == null){ Node<T> node1 = new Node<>(value,null); root = node1;//空樹,插入的爲根節點 return node1; } if(node.value == value){ return node; }else if(node.value > value){ if(node.right == null){ Node<T> node1 = new Node<>(value,node); node.right = node1; return node1; }else if(node.right.value == value){ return node.right; } node = node.right; }else if(node.value < value){ if(node.left == null){ Node<T> node1 = new Node<>(value,node); node.left = node1; return node1; }else if(node.left.value == value){ return node.left; } node = node.left; } } }
爲了解決二叉查找樹的不平衡,2-3樹孕育而生,2-3樹可以很好的實現樹的平衡。
2-3樹的節點再也不是單一的2節點,節點多是2節點、3節點。
2節點:有一個值,兩個子節點
3節點:有兩個值,三個子節點。
注意二叉查找樹是向下生長,而2-3樹是向上生長。
當2-3的根節點由3樹生長爲(紅黑樹中的旋轉)2節點,樹的高度增長。
2-3樹的查找和二叉查找樹的思路是相同的都是迭代的思想。不過不一樣的是在判斷節點是否相同時2-3樹要判斷是否相等於左值或右值,若是大於左值小於右值,則從中子節點開始遞歸。
2-3樹的插入有如下幾種狀況:
插入的節點做爲根節點而且爲2節點。
插入的節點爲2節點,2節點轉化爲3節點。
插入的節點爲3節點,則臨時調整3節點爲4節點(三個值),4節點中的中值變爲左右值的父。
則4節點,轉化爲3個2節點。
則4節點的中子轉化爲父節點的值,父節點轉化爲3節點。
則3節點的中子節點轉爲父節點的值,父節點臨時轉化爲4節點,此時就變成了插入的節點爲3節點的狀況上面的兩種狀況。
經過對比,2-3和二叉樹的上圖的插入,能夠看到2-3最終是會自平衡的,而二叉查找樹最壞會變成鏈表的形式(長的像鏈表).
紅黑樹實際上是2-3樹的一種只含2節點的表現形式。仍是二叉樹節點大於左子節點,小於右子節點。
咱們把2-3樹中的2節點用黑色表示,3節點用紅色表示(3節點的左節點爲黑色、右節點爲紅色)
將紅色連接畫平就是2-3樹。
左旋、右旋其實就是2-3樹的3節點臨時變爲4節點,4節點的分解。
把紅黑樹的插入當作是2-3樹的插入,就能明白紅黑樹的節點插入,節點的旋轉,及根據紅黑樹的
對比2-3的幾種插入狀況,就能理解紅黑樹的插入狀況。
https://github.com/CarpenterL...
一個紅黑樹生成過程: https://www.cs.usfca.edu/~gal...
張無忌的回答:
https://www.zhihu.com/questio...
建議看一下《算法》第四版紅皮書。
其實理解紅黑樹起來也不是那麼困難。
<br/><br/>
關注個人公衆號第一時間閱讀有趣的技術故事
掃碼關注:也能夠在微信搜索公衆號便可關注我:codexiulian 渴望與你一塊兒成長進步!