Java集合-TreeMap和紅黑樹

TreeMap是一種通過實現(xiàn)了紅黑樹數據結構的Map集合溜腐。

【圖片有英文注釋的均摘抄于國外文章】

首先伏穆,先來看一些基礎概念窥妇。

1. 二叉排序樹

二叉排序樹的定義和性質:
(1)若左子樹不空就谜,則左子樹上所有結點的值均小于或等于它的根結點的值怪蔑;
(2)若右子樹不空,則右子樹上所有結點的值均大于或等于它的根結點的值丧荐;
(3)左缆瓣、右子樹也分別為二叉排序樹;
【摘自百度百科】
.
如下圖是一個普通的二叉樹結構:

二叉樹【摘抄于國外文章】

上圖是相應的根據值比較生成的一個簡單的二叉樹虹统,那么對應查找就非常簡單弓坞,不斷通過比較節(jié)點的值,大于就向右子樹走车荔,小于就往左子樹走渡冻,相同則返回當前值.

二叉樹查找【摘抄于國外文章】

對應插入就可以類似查找,先查到當前值于節(jié)點比較忧便,如果找到族吻,直接更新,沒有找到就不斷往子節(jié)點尋找,直到到達為空的子節(jié)點呼奢,將值填入到該空節(jié)點上宜雀。


二叉樹插入【摘抄于國外文章】

二叉樹查找的時候,查找的效率和樹的形狀有關握础,當節(jié)點完全平衡時(最底層子節(jié)點到根節(jié)點的“路程”相同)辐董,效率最高;當所有節(jié)點都只有一個子節(jié)點時禀综,效率最差

二叉樹效率【摘抄于國外文章】

2. B樹

B-樹是一種多路搜索樹(并不一定是二叉的)
如下圖简烘,節(jié)點內有多個值(多路):


B樹【摘抄于國外文章】

上圖展示的最多只有兩個三個子節(jié)點的B樹,這種簡單結構的樹可以稱為2-3樹定枷,這里點到為止孤澎,后續(xù)將通過這種樹去分析后續(xù)的紅黑樹

3. 2-3樹

2-3樹允許每個節(jié)點保存1個或2個值,含有1個值節(jié)點稱為2-node(有兩個子節(jié)點)欠窒,含有2個值的節(jié)點稱為3-node(有三個子節(jié)點)覆旭。
如圖:


2-3樹【摘抄于國外文章】

在2-3樹中查找,與二叉樹類似岖妄,通過不斷和節(jié)點比較進行向下查找型将,需要注意的是,在3-node節(jié)點中荐虐,需要同時比較兩個值七兜,如果介于兩個值之間,需要找的子節(jié)點就是中間的子節(jié)點福扬。

2-3樹查找過程【摘抄于國外文章】

這里重點討論一下插入操作腕铸,首先看一種簡單的,往2-node節(jié)點插入铛碑;如果找到的末節(jié)點是一個2-node的節(jié)點狠裹,直接在此節(jié)點上新增當前值,將其節(jié)點變成3-node節(jié)點亚茬,如圖:


2-3樹2-node新增【摘抄于國外文章】

當插入的節(jié)點是3-node節(jié)點時酪耳,應該怎么操作?首先看一下一個最簡單的刹缝,只有一個3-node節(jié)點的樹:


2-3樹3-node根新增【摘抄于國外文章】

首先,將值插入到當前的3-node節(jié)點颈将,將其變成4-node節(jié)點梢夯,然后提取中間的值,讓其分解為一個普通的二叉樹即可晴圾。

那么如果當前插入的3-node節(jié)點有父節(jié)點時應該怎么處理呢颂砸,首先還是將3-node變成4-node節(jié)點,然后拆解出一個父節(jié)點插入到原來的父節(jié)點中,如果當前父節(jié)點是2-node節(jié)點人乓,那么將其變成3-node節(jié)點勤篮,如果原來父節(jié)點已經是3-node節(jié)點,那么循環(huán)上面的處理步驟色罚。

2-3樹3-node根新增【摘抄于國外文章】
2-3樹3-node根新增【摘抄于國外文章】

總結一下步驟:

  1. 查找需要插入值的位置
  2. 判斷當前插入節(jié)點是否是2-node節(jié)點碰缔,如果是,則將其變成3-node節(jié)點戳护,如不是金抡,繼續(xù)執(zhí)行一下步驟
  3. 將當前節(jié)點變成4-node節(jié)點
    4.分解當前4-node節(jié)點,判斷當前節(jié)點是否為根節(jié)點腌且,如果是梗肝,將整個2-3樹,提高一層铺董,如不是巫击,繼續(xù)執(zhí)行一下步驟
  4. 新增的上層節(jié)點插入到父節(jié)點中,重復執(zhí)行2-4步精续,直到結束

4. 紅黑樹

紅黑樹是一種解決平衡二叉樹的方法喘鸟。紅黑樹具有以下性質:

  1. 節(jié)點是紅色或黑色。
  2. 根節(jié)點是黑色驻右。
  3. 每個葉節(jié)點(NIL節(jié)點什黑,空節(jié)點)是黑色的。
  4. 每個紅色節(jié)點的兩個子節(jié)點都是黑色堪夭。(從每個葉子到根的所有路徑上不能有兩個連續(xù)的紅色節(jié)點)
    5.從任一節(jié)點到其每個葉子的所有路徑都包含相同數目的黑色節(jié)點愕把。
    【摘自百度百科】
紅黑樹【摘抄于國外文章】

紅黑樹其實是2-3樹的一種二叉樹表現(xiàn)方法,如果將紅線連接線水平連接森爽,那么連接的兩個節(jié)點就是2-3樹中的3-node節(jié)點恨豁,其他沒有紅線連接的就是2-3樹中的2-node節(jié)點,如圖:

紅黑樹與2-3樹【摘抄于國外文章】

在講解插入操作前爬迟,先了解集中紅黑樹的平衡操作橘蜜。第一種是左旋轉和右旋轉:

左旋轉【摘抄于國外文章】
右旋轉【摘抄于國外文章】

第二種是顏色反轉,當出現(xiàn)一個節(jié)點下的兩個節(jié)點均是紅色時付呕,可以轉換到2-3樹中思考计福,這是一個4-node節(jié)點,那么需要將其分解為一個二叉樹徽职,并向上合并:

顏色轉換【摘抄于國外文章】

有了2-3樹的插入講解象颖,這邊,直接分析最復雜的紅黑樹插入:

紅黑樹插入【摘抄于國外文章】
  1. 查找需要插入值的位置
  2. 新插入的節(jié)點元素用紅色標識(2-3樹中插入到2-node節(jié)點姆钉,將其變成3-node節(jié)點)
  3. 如果出現(xiàn)節(jié)點下的兩個子節(jié)點都是紅色時(4-node節(jié)點),需要進行顏色轉換(或旋轉)

選取紅黑樹比完全平衡二叉樹的好處就是说订,紅黑樹是一種代價較小就可以實現(xiàn)較平衡的二叉樹的結構抄瓦,最差的情況也就是比完全二叉樹的深度多一倍,但是在刪除操作的平衡里面可以節(jié)省很多的效率陶冷。

5. TreeMap

通過分析二叉樹和紅黑樹的概念钙姊,再來看源碼,首先看TreeMap的容器:

private transient Entry<K,V> root = null;

其中埂伦,TreeMap重寫了Entry類:

K key;
V value;
Entry<K,V> left = null;
Entry<K,V> right = null;
Entry<K,V> parent;

其中key value是為了實現(xiàn)Map的鍵值結構煞额,left、right赤屋、parent表示的是二叉樹中一個節(jié)點與其他節(jié)點的關系指針立镶。

TreeMap提供了節(jié)點值比較的接口:

private final Comparator<? super K> comparator;

接下來,看一下put方法:

public V put(K key, V value) {
    Entry<K,V> t = root;
    ... ...
    int cmp;
    Entry<K,V> parent;
    // split comparator and comparable paths
    Comparator<? super K> cpr = comparator;
    if (cpr != null) {
        do {
            parent = t;
            cmp = cpr.compare(key, t.key);
            if (cmp < 0)
                t = t.left;
            else if (cmp > 0)
                t = t.right;
            else
                return t.setValue(value);
        } while (t != null);
    }
    ... ...
    fixAfterInsertion(e);
    ... ...
}

首先獲取當前的比較器,運用當前比較器作為后續(xù)比較的工具(比較器為空則用默認的,默認的邏輯和有比較器的類似,不重復分析).然后小于类早,則跳到左邊的節(jié)點繼續(xù)比較媚媒,如果大于則在右邊子節(jié)點比較,如果相同涩僻,則設置當前值缭召。然后調用fixAfterInsertion平衡紅黑樹操作。

先偷一下懶逆日,里面的平衡源碼就不分析了嵌巷。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市室抽,隨后出現(xiàn)的幾起案子搪哪,更是在濱河造成了極大的恐慌,老刑警劉巖坪圾,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件晓折,死亡現(xiàn)場離奇詭異,居然都是意外死亡兽泄,警方通過查閱死者的電腦和手機漓概,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來病梢,“玉大人胃珍,你說我怎么就攤上這事◎涯埃” “怎么了觅彰?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長护奈。 經常有香客問我缔莲,道長,這世上最難降的妖魔是什么霉旗? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任痴奏,我火速辦了婚禮,結果婚禮上厌秒,老公的妹妹穿的比我還像新娘读拆。我一直安慰自己,他們只是感情好鸵闪,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布檐晕。 她就那樣靜靜地躺著,像睡著了一般蚌讼。 火紅的嫁衣襯著肌膚如雪辟灰。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天篡石,我揣著相機與錄音芥喇,去河邊找鬼。 笑死凰萨,一個胖子當著我的面吹牛继控,可吹牛的內容都是我干的。 我是一名探鬼主播胖眷,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼武通,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了珊搀?” 一聲冷哼從身側響起冶忱,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎境析,沒想到半個月后囚枪,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡簿晓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年眶拉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片憔儿。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡忆植,死狀恐怖,靈堂內的尸體忽然破棺而出谒臼,到底是詐尸還是另有隱情朝刊,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布蜈缤,位于F島的核電站拾氓,受9級特大地震影響,放射性物質發(fā)生泄漏底哥。R本人自食惡果不足惜咙鞍,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一房官、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧续滋,春花似錦翰守、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至朗恳,卻和暖如春湿颅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粥诫。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工油航, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人臀脏。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓劝堪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揉稚。 傳聞我的和親對象是個殘疾皇子秒啦,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內容