淺談樹形結構:多叉樹,紅黑樹,堆,Trie樹,B樹,B+樹...

2021-02-19 Java面試攻略

應用場景:
二叉查找樹的有序性是它能夠廣泛應用的原因。但是能否高效二分體現在樹的高度合理性上。下面要講的 紅黑樹/堆結構才是其廣泛應用。

紅黑樹

二叉查找樹的缺點在於:只限制了節點的有序性,但有序樹的構造有好壞。一顆「壞」的有序樹直接會被拉成 「有序鍊表」。所以需要通過一定的條件保證樹的平衡性。

樹的平衡性是指整棵樹的最高子樹和最矮子樹相差不大,這樣整棵樹的高度相對來說低一些,相應的增,刪,改,查操作的效率較高較穩定(與樹高有關)。

紅黑樹(Red–black tree)是應用很廣泛的一種平衡樹,是面試官的裝X利器。我們來看一下它保證平衡性的一些特性:

節點是紅色或黑色。

根是黑色。

所有葉子都是黑色(葉子是NIL節點)。

每個紅色節點必須有兩個黑色的子節點。(從每個葉子到根的所有路徑上不能有兩個連續的紅色節點。)

從任一節點到其每個葉子的所有簡單路徑都包含相同數目的黑色節點。

這些約束確保了紅黑樹的關鍵特性:從根到葉子的最長路徑不多於最短路徑的兩倍長(根據性質4和性質5)。從而整棵樹的高度比較穩定,相應的增、刪、改、查操作的效率較高較穩定,而不同於普通的二叉查找樹。

此外相比其他的平衡樹:如高度平衡樹AVL樹,紅黑樹的增刪改效率較高,同時查找性能沒有下降很多也比較穩定。所以工業級應用更為廣泛。

應用場景:適合排序,查找的場景。
1.容器的基本組成,如Java中的HashMap/TreeMap.
2.Linux內核的完全公平調度器
3.Linux中epoll機制的實現…

堆是一種特殊的數據結構,它滿足兩個特性:

堆是一個完全二叉樹;

堆中每一個節點的排序值都必須大於等於(或小於等於)其左右子節點的排序值。

這裡解釋一下完全二叉樹。它是指:除了最後一層,其他層的節點個數都是滿的,最後一層的節點都靠左排列。

這樣我們就可以用數組來存儲。

假設根節點在i=0的位置:如果父節點的數組下標為i,則左子節點的數組下標為2 * i+1,右子節點的數組下標為 2 * i + 2。數組比鍊表的存儲好處上篇文章233醬提過了,這裡就不贅述了。

針對第2點,如果每個節點的值都大於等於子樹中每個節點值的堆,叫做「大頂堆」。反之叫做「小頂堆」。

堆這種結構相對有序,且堆頂元素要麼最小,要麼最大。且利用了 數組和自身特性 增刪改查的時間複雜度較低。

應用場景:
1.堆排序
2.TopK,求中位數,求
3.合併多個有序小文件或集合
4.優先隊列,如定時任務的存儲等…

Trie樹

Trie樹 又稱前綴樹或字典樹,它是一種專門處理字符串匹配的數據結構,用來解決在一組字符串集合中快速查找某個字符串的問題。

它的特性為:

根節點不包含字符,除根節點外的每一個子節點都包含一個字符。

從根節點到某一節點,路徑上經過的字符連接起來,就是該節點對應的字符串。

每個字符串的公共前綴作為一個字符節點保存。

如果我們有and,as,at,cn,com這些關鍵詞,那麼構建的trie樹如下:

Trie 樹的本質,就是利用字符串之間的公共前綴,將重複的前綴合併在一起。這樣當我們查找某個字符串時,只需要在Trie樹上匹配字符串的每個字符,比較次數僅和 字符串的長度 有關。

但是Trie 樹的缺點就是構造Trie樹需要很大的內存空間。因為父子字符節點之間用 指針關聯。如果用數組保存這些指針,這意味著子節點的數組需要窮舉出每一種可能。如子節點字符為a-z,就需要分配長度為26的數組來存儲這些可能的子節點。

改進內存分配的措施有:

1.子節點指針改為用:有序數組、跳表、散列表、紅黑樹來存儲。
2.子節點合併,如原來 hello存儲為:h->e->l->l->o ,現在可存儲為:h->e->llo

Trie 樹畢竟比較浪費空間,所以它在字符串的查找中,適合用於:1.字符集不能太大 2.字符串的公共前綴較多 的場景。

應用場景:
1.關鍵詞匹配,提示,糾錯。
2.最長公共前綴匹配。
3.命令自動補全,如zsh.
4.網址瀏覽歷史記錄。
5.手機號碼簿查詢…

B樹、B+樹 是資料庫中經常出現的數據結構。對於資料庫的增刪改查效率,需要考慮的首要因素是:磁碟的IO訪問次數

如何減少IO訪問次數?

前文我們已經提到了索引,但是IO一次不容易,從磁碟中獲取數據通常是以塊為單位的。如果對於上千萬條數據,我們只建立一層索引結構的話,那索引的數據量也是巨大的。

如何降低索引量?

假設我們到全世界找一個人,我們是按照 國家/省/市/區/街道/小區的順序來定位。同理,隨著數據量的增大,我們需要一層層的建立 多級索引 。越上層的索引每個塊中表示的數據範圍越大。

如何保證我們建立的多級索引 是「合適」的?

這個合適主要指:存儲的數據量大並且樹高小。同紅黑樹一樣,我們需要一些 限制條件 來保證樹高。這也就是以下數據結構的限制條件原因了。

B樹

一個m階(該樹每個節點最多有 M 個子節點)的B樹具有以下特徵:

1.根節點至少有兩個子女。
2.每個中間節點都包含k-1個元素和k個孩子,其中 m/2 <= k <= m
3.每一個葉子節點都包含k-1個元素,其中 m/2 <= k <= m
4.所有的葉子節點都位於同一層。
5.每個節點中的元素從小到大排列,節點當中k-1個元素正好是k個子節點包含的元素的值域分劃。

一個3階的B樹插入示意圖如下:

應用場景:MongoDB

B+樹

一個m階的B+樹具有以下特徵:

1.有k個子樹的中間節點包含有k個元素(B樹中是k-1個元素),每個元素不保存數據,只用來索引,所有數據都保存在葉子節點。
2.所有的葉子節點中包含了全部元素的信息,及指向含這些元素記錄的指針,且葉子節點本身依關鍵字的大小自小而大順序連結。
3.所有的中間節點元素都同時存在於子節點,在子節點元素中是最大(或最小)元素。

看不懂沒關係,我們只需要知道這些限制條件是為了讓B+樹數據「矮而胖」就好。

這裡我直接放張掘金小冊《從根兒上理解MYSQL》B+樹主鍵索引的示意圖:

應用場景
1.Mysql InnoDB存儲引擎。

看到這裡常考面試題來了:B樹和B+樹有什麼區別?為什麼Mongo用B樹?為什麼Mysql用B+樹?

B樹 vs B+樹

看圖說話,B樹 和 B+樹顯著不同的地方是:
1.B樹非葉子節點即是索引,也是數據;B+樹非葉子節點僅是索引,數據全部存儲在葉子節點。
2.B+樹葉子節點的數據之間是用鍊表連結的。
這會導致:

B+樹相比B樹:

1.數據的連續性:B+樹葉子節點上一頁存儲的數據是連續的,當需要一個節點上的數據時,B+樹可以增大緩存的命中率。

2.葉子節點之間的連接性:當作範圍或全文掃描時,B+樹可以依賴葉子節點做線性順序掃描,而B樹只能在每一層的節點上做掃描。B+樹同樣可以增大緩存的命中率。

B樹相比B+樹:
當作單一數據查詢時,B樹的節點平均離根節點更近,平均查詢效率比B+樹快。

總結一下:B+樹相比B樹,前者更適合範圍查詢,後者更適合單一數據查詢。

Mongo是非關係型資料庫,數據之間的關係用嵌套解決。它的主要使用場景是:追求 單個讀寫記錄的性能。

Mysql是關係型資料庫,數據之間的關係用共同的索引鍵,Join解決。它的使用場景:不僅存在大量的單一數據查詢,也存在大量的範圍查詢。

所以上面的問題可以簡單扯一扯了吧。

相關焦點

  • 多叉樹,紅黑樹,堆,Trie樹,B樹,B+樹...
    應用場景:二叉查找樹的有序性是它能夠廣泛應用的原因。但是能否高效二分體現在樹的高度合理性上。下面要講的 紅黑樹/堆結構才是其廣泛應用。紅黑樹二叉查找樹的缺點在於:只限制了節點的有序性,但有序樹的構造有好壞。一顆「壞」的有序樹直接會被拉成 「有序鍊表」。所以需要通過一定的條件保證樹的平衡性。
  • Trie樹結構
    一個節點的所有子孫都有相同的前綴,也就是這個節點對應的字符串,而根節點對應空字符串。一般情況下,不是所有的節點都有對應的值,只有葉子節點和部分內部節點所對應的鍵才有相關的值。Trie這個術語來自於retrieval。根據詞源學,trie的發明者Edward Fredkin把它讀作英語發音:/ˈtriː/ "tree"。
  • 深入理解Trie樹
    前言前面的文章介紹過各種高效的的數據結構,比如二叉搜索樹,AVL樹,紅黑樹,B樹,跳躍表等,今天我們再來學習一種多路樹,叫做Trie樹。
  • 【數據結構與算法圖文動畫詳解】終於可以徹底弄懂:紅黑樹、B-樹、B+樹、B*樹、滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜索樹
    除了圖1表示樹的方法外,還有其他表示方法:使用場景:紅黑樹多用於搜索,插入,刪除操作多的情況下紅黑樹應用比較廣泛:1.廣泛用在C++的STL中。map和set都是用紅黑樹實現的。2.著名的linux進程調度Completely Fair Scheduler,用紅黑樹管理進程控制塊。
  • Trie 樹是什麼樣的數據結構?有哪些應用場景?
    與二叉查找樹不同,鍵不是直接保存在節點中,而是由節點在樹中的位置決定。一個節點的所有子孫都有相同的前綴,也就是這個節點對應的字符串,而根節點對應空字符串。讓我們一起來學習下它吧。一、什麼是Trie樹Trie樹,又叫字典樹、前綴樹(Prefix Tree)、單詞查找樹 或 鍵樹,是一種多叉樹結構。
  • 什麼是 Trie 樹?
    節點 n 存在子節點 o,不用重新創建子節點 o。節點 v 不存在子節點 a,創建子節點 a。並將該節點標記為字符串結束標誌,完成 nova 字符串插入。情況一:待刪除的字符串末尾為葉節點,且與其它字符串無公共前綴。將節點逐一刪除即可,例如刪除 cat。情況二:待刪除字符串末尾不是葉節點。將字符串標誌位置為 false 即可,例如刪除 no 。情況三:待刪除字符串末尾為葉節點,並且中間有其它單詞。
  • 結構與算法:二叉樹與多叉樹
    一、樹狀結構1、數組與鍊表數組結構數組存儲是通過下標方式訪問元素,查詢速度快,如果數組元素是有序的,還可使用二分查找提高檢索速度;如果添加新元素可能會導致多個下標移動,效率較低;鍊表結構鍊表存儲元素,對於元素添加和刪除效率高
  • 樹 Story —— B 樹 / B+ 樹
    本文詳細闡述了多路查找樹原理,適合新手閱讀,以及老手回顧。用過 MySQL 的朋友一定對 B+ 樹不陌生,MySQL 的索引結構就是 B+ 樹。
  • b樹和b+樹的區別是什麼?b+樹數據結構詳細介紹
    B樹即二叉搜索樹,所有非葉子結點至多擁有兩個兒子(Left和Right,所有結點存儲一個關鍵字,非葉子結點的左指針指向小於其關鍵字的子樹,右指針指向大於其關鍵字的子樹。那麼b+樹和b+樹的區別是什麼?以下是b+樹數據結構詳細介紹。
  • b樹和b+樹有什麼不同 b樹和b+樹特點區別匯總
    首頁 > 問答 > 關鍵詞 > b樹最新資訊 > 正文 b樹和b+樹有什麼不同 b樹和b+樹特點區別匯總
  • 算法連載之紅黑樹
    若新增節點<4>的叔節點<8>為紅色,則:a、將父節點<5>和叔節點<8>標記為黑色;多了一層黑色節點,違反性質5b、修正a,將祖父節點<7>標記為紅色。
  • B+樹是什麼意思 B+樹怎麼理解
    首頁 > 問答 > 關鍵詞 > b+樹最新資訊 > 正文 B+樹是什麼意思 B+樹怎麼理解
  • SQL-資料庫索引選擇B+樹的原因
    在進一步分析為什麼MySQL資料庫索引選擇使用B+樹之前,我相信很多小夥伴對數據結構中的樹還是有些許模糊的,因此我們由淺入深一步步探討樹的演進過程,在一步步引出B樹以及為什麼MySQL資料庫索引選擇使用B+樹!學過數據結構的一般對最基礎的樹都有所認識,因此我們就從與我們主題更為相近的二叉查找樹開始。
  • 樹型結構詳解
    本文探討另外一種重要的數據結構----樹,其大部分時間可以保證操作的運行平均時間複雜度為O(logN),第一部分先來看一下樹的一些預備知識。首先看一下樹形結構的樣子,下圖代表的是樹型結構的一般形態:二叉樹的一個性質是一顆平均二叉樹的深度要比及結點個數N小得多,這個性質很重要,尤其對於特殊類型的二叉樹即二叉查找樹而言,其深度的平均值是O(logN),這將大大降低查找時的時間複雜度。
  • MySQL的索引結構為什麼使用B+樹?
    但紅黑樹的刪除效率大大提高了,因為紅黑樹同時引入了顏色,當插入或刪除數據時,只需要進行O(1)次數的旋轉以及變色就能保證基本的平衡,不需要像AVL樹進行O(lgn)次數的旋轉。總的來說,紅黑樹的統計性能高於AVL。因此,在實際應用中,AVL樹的使用相對較少,而紅黑樹的使用非常廣泛。
  • 「算法與數據結構」Trie樹之美
    前言這次分享的Trie字典樹,是數據結構專題中的一個分支,認識了解Trie這種樹型數據結構,對構建算法與數據結構知識體系有一定的幫助。我對Trie樹的理解:把字符串都串接起來,消滅不必要的存儲,利用的就是字符串的公共前綴。
  • 算法-B樹和B+樹總結
    簡介 在計算機科學中,B樹(英語:B-tree)是一種自平衡的樹,能夠保持數據有序。這種數據結構能夠讓查找數據、順序訪問、插入數據及刪除的動作,都在對數時間內完成。B樹,概括來說是一個一般化的二叉查找樹(binary search tree),可以擁有多於2個子節點。
  • 騰訊面試題:有了二叉查找樹、平衡樹為啥還需要紅黑樹?
    本文作者:帥地紅黑樹算是很難的一種數據結構吧,一般很少考察插入、刪除等具體操作步驟,如果遇到要你手寫紅黑樹的面試官,就直接告辭吧。所以,更多是會考察你對紅黑樹的理解程度,考察的最多的估計就是為什麼有了二查找查找樹/平衡樹還需要紅黑樹這個問題了,今天,你只需要花一分鐘的時間,就知道怎麼回答這個問題了。
  • MySQL索引底層:B+樹詳解
    對於範圍查詢,索引的底層結構就是B+樹。今天我們一起來學習一下B+樹哈~公眾號:「撿田螺的小男孩」樹的簡介樹的簡介樹跟數組、鍊表、堆棧一樣,是一種數據結構。它由有限個節點,組成具有層次關係的集合。因為它看起來像一棵樹,所以得其名。
  • 漫畫:什麼是紅黑樹?
    什麼情況下會破壞紅黑樹的規則,什麼情況下不會破壞規則呢?我們舉兩個簡單的慄子:1.向原紅黑樹插入值為14的新節點:由於父節點15是黑色節點,因此這種情況並不會破壞紅黑樹的規則,無需做任何調整。2.向原紅黑樹插入值為21的新節點: