集合框架 (第 10 篇) 源碼分析:二叉樹缰趋、平衡二叉樹捧杉、二叉查找樹、AVL樹秘血、紅黑樹

一味抖、集合框架源碼分析

原文持續(xù)更新鏈接: https://github.com/about-cloud/JavaCore

正文


tree

一、樹

浩瀚宇宙蓖乘,從 點(diǎn)韧骗,嘉抒,組成了豐富多彩的世界。動(dòng)物袍暴、植物和其他物體正是存儲(chǔ)在 宇宙 這個(gè)數(shù)據(jù)結(jié)構(gòu)中些侍。

前幾篇文章介紹了 線性 的數(shù)據(jù)結(jié)構(gòu): ArrayList隶症、LinkedList及其組合HashMap。從 線性 數(shù)據(jù)結(jié)構(gòu)到 非線性 數(shù)據(jù)結(jié)構(gòu)岗宣,就像 樹干 發(fā)叉一樣:

line to tree

從數(shù)據(jù)結(jié)構(gòu)進(jìn)化的角度來看蚂会,樹(tree) 的生成是 鏈表 進(jìn)化而來。鏈(Linked) 每個(gè)節(jié)點(diǎn)最多只有一個(gè) 前驅(qū)節(jié)點(diǎn) 耗式,那么可以稱這個(gè) 為 ??樹(tree) 胁住。數(shù)據(jù)結(jié)構(gòu)中的樹就像一顆倒掛的樹。

鏈表 只不過是特殊的樹刊咳,就像樹沒有樹枝只有樹干一樣彪见。

樹的基本術(shù)語

  1. 節(jié)點(diǎn)(Node):樹中的每個(gè)元素稱為 節(jié)點(diǎn)(Node);
  2. 根節(jié)點(diǎn)(Root Node):樹最頂端的節(jié)點(diǎn)被稱為根節(jié)點(diǎn)(樹根)娱挨,根節(jié)點(diǎn)無父節(jié)點(diǎn)余指;
  3. 父節(jié)點(diǎn)(Parent Node):節(jié)點(diǎn)的(上面的)前驅(qū)節(jié)點(diǎn)在樹中被稱為父節(jié)點(diǎn);
  4. 子節(jié)點(diǎn)(Child Node):(下面的)后繼節(jié)點(diǎn)被稱為子節(jié)點(diǎn)跷坝;
  5. 子樹(Subtree):子節(jié)點(diǎn)及其下面的節(jié)點(diǎn)組成的樹稱為子樹 酵镜;
  6. 一棵樹最多只有一個(gè)根節(jié)點(diǎn),樹中的每個(gè)子節(jié)點(diǎn)最多只有一個(gè)父節(jié)點(diǎn)柴钻;
  7. 節(jié)點(diǎn)的度:一個(gè)節(jié)點(diǎn)含有的子樹的個(gè)數(shù)稱為該節(jié)點(diǎn)的度(葉子節(jié)點(diǎn)的度為0)淮韭;
  8. 葉節(jié)點(diǎn)(Leaf Node)(葉子節(jié)點(diǎn)或終端節(jié)點(diǎn)):度為0的節(jié)點(diǎn)稱為葉節(jié)點(diǎn)(也就是沒有子節(jié)點(diǎn)的節(jié)點(diǎn)稱為葉子節(jié)點(diǎn));
  9. 非終端節(jié)點(diǎn) 或分支節(jié)點(diǎn):度不為0的節(jié)點(diǎn)(擁有子節(jié)點(diǎn)的節(jié)點(diǎn))顿颅;
  10. 兄弟節(jié)點(diǎn):具有相同父節(jié)點(diǎn)的節(jié)點(diǎn)互稱為兄弟節(jié)點(diǎn)缸濒;
  11. 樹的度:一棵樹中,節(jié)點(diǎn)中最大的度稱為樹的度粱腻;
  12. 節(jié)點(diǎn)的層次:從根開始定義起庇配,根為第1層,根的子節(jié)點(diǎn)為第2層绍些,以此類推捞慌;
  13. 樹的高度或深度:樹中節(jié)點(diǎn)的最大層次;
  14. 堂兄弟節(jié)點(diǎn):雙親在同一層的節(jié)點(diǎn)互為堂兄弟柬批;
  15. 節(jié)點(diǎn)的祖先:從該節(jié)點(diǎn)上溯至根節(jié)點(diǎn)啸澡,所經(jīng)分支上的所有節(jié)點(diǎn);
  16. 子孫節(jié)點(diǎn):該節(jié)點(diǎn)下面所有所有的節(jié)點(diǎn)稱為該節(jié)點(diǎn)的子孫節(jié)點(diǎn)氮帐;
  17. 空樹:沒有節(jié)點(diǎn)的樹稱為空樹嗅虏;
  18. 森林:由多棵互不相交(沒有重疊節(jié)點(diǎn))的樹組成的集合稱為森林(單棵樹可以認(rèn)為是特殊的森林);

二上沐、二叉樹

二叉樹是每個(gè)節(jié)點(diǎn)最多只有兩個(gè)子樹的樹皮服。子樹通常被稱為左子樹(Left subtree)右子樹(Right subtree)

BinaryTree

二叉樹的特性

  1. 在非空二叉樹的 i 層上,至多有 2^{i-1}個(gè)節(jié)點(diǎn)(i>=1)龄广;
  2. 在深度為 d 的二叉樹上最多有 2d-1 個(gè)結(jié)點(diǎn)(d>=1);
  3. 對(duì)于任何一棵非空的二叉樹,如果葉節(jié)點(diǎn)個(gè)數(shù)為 n0硫眯,度數(shù)為 2 的節(jié)點(diǎn)個(gè)數(shù)為 n2,則有: n0 = n2 + 1择同。

二叉樹的遍歷

二叉樹遍歷:從樹的根節(jié)點(diǎn)出發(fā)两入,按照某種 次序 依次訪問二叉樹中所有的節(jié)點(diǎn),使得每個(gè)節(jié)點(diǎn)被訪問僅且一次敲才。

這里有兩個(gè)關(guān)鍵詞:訪問次序裹纳。訪問 包括 增刪改查次序 包括 前序归斤、中序痊夭、后序前中后是以樹的根節(jié)點(diǎn)作為參照物脏里,又規(guī)定不管如何遍歷 左子樹 的訪問順序要排在 右子樹 前面(左邊)她我。

1、前序遍歷(先序遍歷)

遍歷步驟:先訪問根節(jié)點(diǎn)迫横,然后再先序遍歷左子樹番舆,最后再先序遍歷右子樹即 根—左—右

先序遍歷

上圖先序遍歷的結(jié)果:

2矾踱、中序遍歷

遍歷步驟:先中序遍歷左子樹恨狈,然后再訪問根節(jié)點(diǎn),最后再中序遍歷右子樹即 左—根—右呛讲。

中序遍歷
中序遍歷

上圖中序遍歷的結(jié)果:

3禾怠、后序遍歷

遍歷步驟:先后序遍歷左子樹,再后序遍歷右子樹贝搁,最后再訪問根節(jié)點(diǎn)吗氏,即 左—右—根

后序遍歷
后序遍歷

上圖后序遍歷的結(jié)果:

三雷逆、平衡二叉樹

平衡二叉樹(Balanced Binary Tree)的 平衡性 體現(xiàn)在以下幾點(diǎn):

  1. 樹的左弦讽、右子樹的 高度差 的絕對(duì)值不超過1;
  2. 任意節(jié)點(diǎn)左膀哲、右子樹也分別平衡二叉樹往产;

一棵數(shù)頻繁的刪除和插入節(jié)點(diǎn)都有可能使數(shù)發(fā)生旋轉(zhuǎn)。平衡二叉樹中訪問節(jié)點(diǎn)的操作(插入某宪、查找仿村、刪除)的時(shí)間復(fù)雜度維持在一個(gè)“平衡”的水準(zhǔn),既最壞情況和最好情況的時(shí)間復(fù)雜度維持在 O(logN)兴喂。

平衡二叉樹
平衡二叉樹

四蔼囊、二叉查找樹

二叉查找樹(二叉搜索樹 Binary Search Tree)的 查找 特性體現(xiàn)在以下幾點(diǎn):

  1. 如果它的左子樹不空包颁,則左子樹上所有節(jié)點(diǎn)的值均小于它的根節(jié)點(diǎn)的值;
  2. 如果它的右子樹不空压真,則右子樹上所有節(jié)點(diǎn)的值均大于它的根節(jié)點(diǎn)的值;
  3. 任意節(jié)點(diǎn)左蘑险、右子樹也分別為二叉查找樹滴肿。
先序遍歷
先序遍歷

二叉查找樹的查找過程

  1. 從樹的根節(jié)點(diǎn)開始查找,并沿著這棵樹中的一條簡單路徑向下進(jìn)行佃迄;
  2. 若樹為空樹泼差,則查找失敗,返回 null呵俏;
  3. 對(duì)于訪問的每個(gè)節(jié)點(diǎn) x堆缘,若指定的值 k 等于結(jié)點(diǎn) x 的值,返回該節(jié)點(diǎn)x 并結(jié)束查找普碎;
  4. 若指定的值 k 小于節(jié)點(diǎn) x 的值吼肥,則在節(jié)點(diǎn) x 的左子樹中查找(根據(jù)上面二叉查找樹的性質(zhì)判斷);
  5. 相反麻车,若指定的值 k 大于節(jié)點(diǎn) x 的值缀皱,則查找在節(jié)點(diǎn) x 的右子樹中繼續(xù);
  6. 若查找至 葉子節(jié)點(diǎn) 后仍未匹配到相等值动猬,則表示不存在指定值的節(jié)點(diǎn)啤斗,返回null。

五赁咙、AVL樹(高度平衡樹)

AVL樹 得名于它的兩位發(fā)明者G. M. Adelson-Velsky和E. M. Landis的名字钮莲,樹的特性是:

  1. :wink:本身首先是一棵二叉查找樹;
  2. 每個(gè)節(jié)點(diǎn)的左右子樹的高度之差的絕對(duì)值(平衡因子)最多為 1
AVL
AVL

ALV追求極限的平衡性彼水,優(yōu)點(diǎn)是在查找元素時(shí)崔拥,時(shí)間復(fù)雜度低,查找元素快猿涨。那么問題來了握童,在添加/刪除元素時(shí),AVL樹為了追求“絕對(duì)的平衡性”叛赚,不斷的通過循環(huán)來達(dá)到自平衡澡绩,增加時(shí)間復(fù)雜度。適所以AVL樹適用于添加/刪除元素少俺附、查找操作多的環(huán)境下肥卡。

六、紅黑樹

紅黑樹(Red Black Tree) 也是一種 平衡二叉樹(而平衡二叉樹又是一種二叉查找樹事镣,所以紅黑樹也是一種二叉查找樹)步鉴,但它不像 AVL樹 那樣追求絕對(duì)的平衡,它這種于查找和添加/刪除之間。特性是:

  1. 樹中所有節(jié)點(diǎn)都被染成紅色??或黑色??(官方話語:節(jié)點(diǎn)是紅色或黑色)氛琢;
  2. 根節(jié)點(diǎn)和葉子節(jié)點(diǎn)都是黑色??
  3. 每個(gè)紅色節(jié)點(diǎn)??的兩個(gè)子節(jié)點(diǎn)都是黑色??(從每個(gè)葉子到根的所有路徑上不能有兩個(gè)連續(xù)的紅色節(jié)點(diǎn)??)喊递;
  4. 從任一節(jié)點(diǎn)到其每個(gè)葉子的所有路徑都包含相同數(shù)目的黑色節(jié)點(diǎn)??。
紅黑樹
紅黑樹

上述特性構(gòu)成了一個(gè)最關(guān)鍵的約束:從根節(jié)點(diǎn)到葉子節(jié)點(diǎn)的最長路徑不大于最短路徑的兩倍長阳似。

所以紅黑樹可以不是那么絕對(duì)的高度平衡骚勘。對(duì)于在樹中添加/刪除元素,紅黑樹也不像AVL樹那樣撮奏,為了達(dá)到絕對(duì)的自平衡而“使勁費(fèi)力”地旋轉(zhuǎn)整顆樹了俏讹。

最差平衡二叉樹即樹退化成鏈表(可以看成特殊的樹、沒有叉的樹)畜吊,這樣的樹添加/刪除元素快泽疆,不需要自平衡,但是查找慢玲献,最壞情況要遍歷整棵樹殉疼。而從增刪改查的時(shí)間復(fù)雜度來講,紅黑樹 介于 二叉查找樹鏈表 之間捌年,這是在添加/刪除和查找之間一個(gè)折中的選擇株依。

總結(jié):

鏈表:適用于添加/刪除多、查找少的場景延窜;

二叉查找樹:適用于查找多恋腕、添加/刪除少的場景;

紅黑樹:適用于查找逆瑞、添加荠藤、刪除都多的場景。

七获高、B-Tree哈肖、B+Tree、B*Tree

這種和MySQL的InnoDB索引息息相關(guān)念秧,單獨(dú)拿出一個(gè)章節(jié)去講解淤井,詳見:

https://github.com/about-cloud/JavaCore

原文持續(xù)更新鏈接: https://github.com/about-cloud/JavaCore

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市摊趾,隨后出現(xiàn)的幾起案子币狠,更是在濱河造成了極大的恐慌,老刑警劉巖砾层,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件漩绵,死亡現(xiàn)場離奇詭異,居然都是意外死亡肛炮,警方通過查閱死者的電腦和手機(jī)止吐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門宝踪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碍扔,你說我怎么就攤上這事瘩燥。” “怎么了不同?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵颤芬,是天一觀的道長。 經(jīng)常有香客問我套鹅,道長,這世上最難降的妖魔是什么汰具? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任卓鹿,我火速辦了婚禮,結(jié)果婚禮上留荔,老公的妹妹穿的比我還像新娘吟孙。我一直安慰自己,他們只是感情好聚蝶,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布杰妓。 她就那樣靜靜地躺著,像睡著了一般碘勉。 火紅的嫁衣襯著肌膚如雪巷挥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天验靡,我揣著相機(jī)與錄音倍宾,去河邊找鬼。 笑死胜嗓,一個(gè)胖子當(dāng)著我的面吹牛高职,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播辞州,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怔锌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了变过?” 一聲冷哼從身側(cè)響起埃元,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎媚狰,沒想到半個(gè)月后亚情,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體误辑,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡厕倍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了视粮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡土浸,死狀恐怖罪针,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情黄伊,我是刑警寧澤泪酱,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站还最,受9級(jí)特大地震影響墓阀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拓轻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一斯撮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扶叉,春花似錦勿锅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至达吞,卻和暖如春张弛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背酪劫。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國打工乌庶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人契耿。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓瞒大,卻偏偏與公主長得像,于是被迫代替她去往敵國和親搪桂。 傳聞我的和親對(duì)象是個(gè)殘疾皇子透敌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容