最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

通過java.util.TreeMap源碼加強(qiáng)紅黑樹的理解

 更新時(shí)間:2017年11月20日 10:34:17   投稿:laozhang  
通過分析java.util.TreeMap源碼來對(duì)經(jīng)典問題紅黑樹加強(qiáng)理解和理清思路。

在此之前,腳本之家已經(jīng)為大家整理了很多關(guān)于經(jīng)典問題紅黑樹的思路和解決辦法。本篇文章,是通過分析java.util.TreeMap源碼,讓大家通過實(shí)例來對(duì)紅黑樹這個(gè)問題有更加深入的理解。

本篇將結(jié)合JDK1.6的TreeMap源碼,來一起探索紅-黑樹的奧秘。紅黑樹是解決二叉搜索樹的非平衡問題。

當(dāng)插入(或者刪除)一個(gè)新節(jié)點(diǎn)時(shí),為了使樹保持平衡,必須遵循一定的規(guī)則,這個(gè)規(guī)則就是紅-黑規(guī)則: 
1) 每個(gè)節(jié)點(diǎn)不是紅色的就是黑色的 
2) 根總是黑色的 
3) 如果節(jié)點(diǎn)是紅色的,則它的子節(jié)點(diǎn)必須是黑色的(反之倒不一定必須為真) 
4) 從跟到葉節(jié)點(diǎn)或者空子節(jié)點(diǎn)的每條路徑,必須包含相同數(shù)目的黑色節(jié)點(diǎn)

插入一個(gè)新節(jié)點(diǎn)

紅-黑樹的插入過程和普通的二叉搜索樹基本一致:從跟朝插入點(diǎn)位置走,在每個(gè)節(jié)點(diǎn)處通過比較節(jié)點(diǎn)的關(guān)鍵字相對(duì)大小來決定向左走還是向右走。

public V put(K key, V value) {
Entry<K,V> t = root;
int cmp;
Entry<K,V> parent;
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);
if (cmp < 0) {
t = t.left;
} else if (cmp > 0) {
t = t.right; 
} else {
// 注意,return退出方法 
return t.setValue(value); 
}
} while (t != null);
Entry<K,V> e = new Entry<K,V>(key, value, parent);
if (cmp < 0) {
parent.left = e;
} else {
parent.right = e;
}
fixAfterInsertion(e);
size++;
modCount++;
return null;
}

但是,在紅-黑樹種,找到插入點(diǎn)更復(fù)雜,因?yàn)橛蓄伾儞Q和旋轉(zhuǎn)。fixAfterInsertion()方法就是處理顏色變換和旋轉(zhuǎn),需重點(diǎn)掌握它是如何保持樹的平衡(use rotations and the color rules to maintain the tree's balance)。

下面的討論中,使用X、P、G表示關(guān)聯(lián)的節(jié)點(diǎn)。X表示一個(gè)特殊的節(jié)點(diǎn), P是X的父,G是P的父。

X is a node that has caused a rule violation. (Sometimes X refers to a newly inserted node, and sometimes to the child node when a parent and child have a redred conflict.)

On the way down the tree to find the insertion point, you perform a color flip whenever you find a black node with two red children (a violation of Rule 2). Sometimes the flip causes a red-red conflict (a violation of Rule 3). Call the red child X and the red parent P. The conflict can be fixed with a single rotation or a double rotation, depending on whether X is an outside or inside grandchild of G. Following color flips and rotations, you continue down to the insertion point and insert the new node.

After you've inserted the new node X, if P is black, you simply attach the new red node. If P is red, there are two possibilities: X can be an outside or inside grandchild of G. If X is an outside grandchild, you perform one rotation, and if it's an inside grandchild, you perform two. This restores the tree to a balanced state.

按照上面的解釋,討論可分為3個(gè)部分,按復(fù)雜程度排列,分別是: 
1) 在下行路途中的顏色變換(Color flips on the way down) 
2) 插入節(jié)點(diǎn)之后的旋轉(zhuǎn)(Rotations after the node is inserted) 
3) 在向下路途上的旋轉(zhuǎn)(Rotations on the way down)

在下行路途中的顏色變換(Color flips on the way down)

Here's the rule: Every time the insertion routine encounters a black node that has two red children, it must change the children to black and the parent to red (unless the parent is the root, which always remains black)

The flip leaves unchanged the number of black nodes on the path from the root on down through P to the leaf or null nodes.

盡管顏色變換不會(huì)違背規(guī)則4,但是可能會(huì)違背規(guī)則3。如果P的父是黑色的,則P由黑色變成紅色時(shí)不會(huì)有任何問題,但是,如果P的父是紅色的,那么在P的顏色變化之后,就有兩個(gè)紅色節(jié)點(diǎn)相連接了。這個(gè)問題需要在繼續(xù)向下沿著路徑插入新節(jié)點(diǎn)之前解決,可以通過旋轉(zhuǎn)修正這個(gè)問題,下文將會(huì)看到。

插入節(jié)點(diǎn)之后的旋轉(zhuǎn)(Rotations after the node is inserted)

新節(jié)點(diǎn)在插入之前,樹是符合紅-黑規(guī)則,在插入新節(jié)點(diǎn)之后,樹就不平衡了,此時(shí)需要通過旋轉(zhuǎn)來調(diào)整樹的平衡,使之重新符合紅-黑規(guī)則。

可能性1:P是黑色的,就什么事情也不用做。插入即可。

可能性2:P是紅色,X是G的一個(gè)外側(cè)子孫節(jié)點(diǎn),則需要一次旋轉(zhuǎn)和一些顏色的變化。 
以插入50,25,75,12,6為例,注意節(jié)點(diǎn)6是一個(gè)外側(cè)子孫節(jié)點(diǎn),它和它的父節(jié)點(diǎn)都是紅色。 

在這個(gè)例子中,X是一個(gè)外側(cè)子孫節(jié)點(diǎn)而且是左子節(jié)點(diǎn),X是外側(cè)子孫節(jié)點(diǎn)且為右子節(jié)點(diǎn),是一種與此對(duì)稱的情況。通過用50,25,75,87,93創(chuàng)建樹,同理再畫一畫圖,這里就省略了。

可能性3:P是紅色,X是G的一個(gè)內(nèi)側(cè)子孫節(jié)點(diǎn),則需要兩次旋轉(zhuǎn)和一些顏色的改變。 
以插入50,25,75,12,18為例,注意節(jié)點(diǎn)18是一個(gè)內(nèi)側(cè)子孫節(jié)點(diǎn),它和它的父節(jié)點(diǎn)都是紅色。 

在向下路途上的旋轉(zhuǎn)(Rotations on the way down)

在插入新節(jié)點(diǎn)之前,實(shí)際上樹已經(jīng)違背了紅-黑規(guī)則,所以需要插入新節(jié)點(diǎn)之前做調(diào)整。所以我們本次討論的主題是“在向下路途準(zhǔn)備插入新節(jié)點(diǎn)時(shí),上面先進(jìn)行調(diào)整,使上面成為標(biāo)準(zhǔn)的紅黑樹后,再進(jìn)行新節(jié)點(diǎn)插入”。

外側(cè)子孫節(jié)點(diǎn)

以插入50,25,75,12,37,6,18,3為例,例子中違背規(guī)則的節(jié)點(diǎn)是一個(gè)外側(cè)子孫節(jié)點(diǎn)。 

內(nèi)側(cè)子孫節(jié)點(diǎn)

以插入50,25,75,12,37,31,43為例,例子中違背規(guī)則的節(jié)點(diǎn)是一個(gè)內(nèi)側(cè)子孫節(jié)點(diǎn)。

紅-黑樹的效率

和一般的二叉搜索樹類似,紅-黑樹的查找、插入和刪除的時(shí)間復(fù)雜度為O(log2N)。

紅-黑樹的查找時(shí)間和普通的二叉搜索樹的查找時(shí)間應(yīng)該幾乎完全一樣。因?yàn)樵诓檎疫^程中并沒用到紅-黑特征。額外的開銷只是每個(gè)節(jié)點(diǎn)的存儲(chǔ)空間都稍微增加了一點(diǎn),來存儲(chǔ)紅黑顏色(一個(gè)boolean變量)。

final Entry<K, V> getEntry(Object key) {
Comparable <? super K > k = (Comparable <? super K > ) key;
Entry<K, V> p = root;
while (p != null) {
int cmp = k.compareTo(p.key);
if (cmp < 0) {
p = p.left;
} else if (cmp > 0) {
p = p.right;
} else {
return p;
}
}
return null;
}

插入和刪除的時(shí)間要增加一個(gè)常數(shù)因子,因?yàn)椴坏貌辉谙滦械穆窂缴虾筒迦朦c(diǎn)執(zhí)行顏色變換和旋轉(zhuǎn)。平均起來一次插入大約需要一次旋轉(zhuǎn)。

因?yàn)樵诖蠖鄶?shù)應(yīng)用中,查找的次數(shù)比插入和刪除的次數(shù)多,所以應(yīng)用紅-黑樹取代普通的二叉搜索樹總體上不會(huì)增加太多的時(shí)間開銷。

相關(guān)文章

  • java中的HashMap多層嵌套

    java中的HashMap多層嵌套

    這篇文章主要介紹了java中的HashMap多層嵌套問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Java中該如何優(yōu)雅的使用線程池詳解

    Java中該如何優(yōu)雅的使用線程池詳解

    在java開發(fā)中我們對(duì)“池”的概念并不陌生,常見的有數(shù)據(jù)庫連接池、線程池、對(duì)象池、常量池等等,其作用基本上就是避免頻繁的創(chuàng)建和回收,造成資源浪費(fèi),線程池也不例外,這篇文章主要給大家介紹了關(guān)于Java中該如何優(yōu)雅的使用線程池的相關(guān)資料,需要的朋友可以參考下
    2021-12-12
  • springboot如何配置多kafka

    springboot如何配置多kafka

    這篇文章主要介紹了springboot如何配置多kafka問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • 深入講解Java中的多態(tài)和抽象類

    深入講解Java中的多態(tài)和抽象類

    這篇文章主要介紹了深入講解Java中的多態(tài)和抽象類,有時(shí)候,設(shè)計(jì)一個(gè)數(shù)組或方法的參數(shù),返回值類型時(shí),無法確定具體的類型,只能確定是某個(gè)系列的類型,這時(shí)就引入了多態(tài),需要的朋友可以參考下
    2023-08-08
  • Java中的Optional類詳細(xì)解讀

    Java中的Optional類詳細(xì)解讀

    這篇文章主要介紹了Java中的Optional類詳細(xì)解讀,Optional是Java中的一個(gè)類,它的作用是用于解決空指針異常的問題,它提供了一些有用的方法,可以幫助我們避免顯式進(jìn)行空值檢測(cè),需要的朋友可以參考下
    2023-08-08
  • Spring實(shí)戰(zhàn)之ServletContextResource訪問資源文件示例

    Spring實(shí)戰(zhàn)之ServletContextResource訪問資源文件示例

    這篇文章主要介紹了Spring實(shí)戰(zhàn)之ServletContextResource訪問資源文件,結(jié)合實(shí)例形式分析了spring使用ServletContextResource讀取與遍歷資源文件相關(guān)操作技巧,需要的朋友可以參考下
    2019-12-12
  • springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼

    springboot整合shiro登錄失敗次數(shù)限制功能的實(shí)現(xiàn)代碼

    這篇文章主要介紹了springboot整合shiro-登錄失敗次數(shù)限制功能,實(shí)現(xiàn)此功能如果是防止壞人多次嘗試,破解密碼的情況,所以要限制用戶登錄嘗試次數(shù),需要的朋友可以參考下
    2018-09-09
  • springboot帶有進(jìn)度條的上傳功能完整實(shí)例

    springboot帶有進(jìn)度條的上傳功能完整實(shí)例

    這篇文章主要介紹了springboot帶有進(jìn)度條的上傳功能,結(jié)合完整實(shí)例形式分析了springboot帶進(jìn)度條上傳的原理、實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2019-11-11
  • 使用eclipse創(chuàng)建java項(xiàng)目的方法

    使用eclipse創(chuàng)建java項(xiàng)目的方法

    這篇文章主要為大家詳細(xì)介紹了使用eclipse創(chuàng)建java項(xiàng)目的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • Java 事務(wù)詳解及簡(jiǎn)單應(yīng)用實(shí)例

    Java 事務(wù)詳解及簡(jiǎn)單應(yīng)用實(shí)例

    這篇文章主要介紹了Java 事務(wù)詳解及簡(jiǎn)單應(yīng)用實(shí)例的相關(guān)資料,java事務(wù)能夠保證數(shù)據(jù)的完整性和一致性,當(dāng)然這是書本上的知識(shí),具體如何應(yīng)用這里舉例說明,需要的朋友可以參考下
    2016-12-12

最新評(píng)論

山西省| 霞浦县| 江达县| 钦州市| 金寨县| 青田县| 光泽县| 荔浦县| 渭南市| 龙山县| 慈利县| 淮南市| 贺州市| 洮南市| 南安市| 宣武区| 青浦区| 林甸县| 大足县| 古交市| 高陵县| 方城县| 嘉义市| 互助| 射阳县| 青海省| 德清县| 肥乡县| 涪陵区| 延吉市| 望谟县| 宣城市| 阿拉善右旗| 沽源县| 合山市| 乐至县| 屏山县| 吴江市| 上思县| 荥经县| 邯郸市|