上篇文章咱們主要介紹了線性數據結構,本篇233醬帶你們康康 無所不在的非線性數據結構之一:樹形結構的特色和應用。面試
樹形結構,是指:數據元素之間的關係像一顆樹的數據結構。咱們看圖說話:
它具備如下特色:sql
維基百科中列舉了計算機科學中樹形結構的種類
233醬固然不會一個個講,咱們只挑一些熟悉的面孔:多叉樹,二叉樹,二叉查找樹,紅黑樹,堆,Trie樹,B樹,B+樹,LSM Tree,瞭解他們在對不一樣規模的數據 增,刪,改,查 時所起到的做用就夠了。mongodb
限於篇幅,本文主要介紹非LSM Tree的內容。數據庫
樹體現了一種 繼承 的關係,節點之間爲父子關係。多叉樹 是指一個父節點能夠有多個子節點。也就是:爸爸能夠有多個兒子,兒子只能有一個爸爸。
當須要這種分層,繼承的場景下都可以考慮用樹結構來實現,能夠簡化咱們對數據關係的描述。數組
此外,節點的每一個分支也表明着一種選擇,能夠用來作決策。緩存
應用場景:
1.Linux文件系統
2.組織關係表示,如公司的組織架構,角色權限系統等。
3.XML/HTML數據。
4.類的繼承關係
5.決策,如遊戲中怪物使用的技能選擇,機器學習...
二叉樹(Binary tree)是每一個節點最多隻有兩個分支(即不存在分支度大於2的節點)的樹結構,也就是說 爸爸 最多隻能有 兩個兒子。
由於計算機應用中存在不少「非黑即白」的場景,一樣咱們能夠利用 不是走左分支,就是走右分支 這種結構選擇來作一些決策。
另外,利用每一個節點下參與方最多爲兩個,也能夠作一些事情。數據結構
應用場景:
1.編譯器的語法樹構造。
2.表達式求值和判斷:非葉子節點爲操做符,葉子節點爲數值。
3.Boolean求值,如(a and b)or (c or d)
。
4.霍夫曼編碼
5.IPv4路由表的存儲...
在咱們的平常開發中,常常須要對數據進行增刪改查,每個步驟的時間空間效率決定了應用最終的性能。架構
時間複雜度 體如今 可否快速定位到要操做的數據元素,核心在於 索引的好壞;機器學習
空間複雜度 體如今 可否佔用 更小的內存空間,可否利用計算機各層介質的緩存性能提升訪問速度(訪問速度:CPU>> 內存>>磁盤)。性能
在如下樹形結構的討論中,但願小夥伴能多從 索引,所佔用內存空間,操做的介質 這些方面考慮數據的增刪改查性能。
二叉查找樹(Binary Search Tree)首先是二叉樹,同時知足必定的有序性:節點的左子節點比本身小,節點的右子節點比本身大。
這樣當咱們定位一個元素的位置時,從根節點開始查找,小於節點左拐,大於節點右拐。等於節點排序值就恰好找到。二分的索引思想就體如今其中。
應用場景:
二叉查找樹的有序性是它可以普遍應用的緣由。可是可否高效二分體如今樹的高度合理性上。下面要講的 紅黑樹/堆結構纔是其普遍應用。
二叉查找樹的缺點在於:只限制了節點的有序性,但有序樹的構造有好壞。一顆「壞」的有序樹直接會被拉成 「有序鏈表」。因此須要經過必定的條件保證樹的平衡性。
樹的平衡性是指整棵樹的最高子樹和最矮子樹相差不大,這樣整棵樹的高度相對來講低一些,相應的增,刪,改,查操做的效率較高較穩定(與樹高有關)。
紅黑樹(Red–black tree)是應用很普遍的一種平衡樹,是面試官的裝X利器。咱們來看一下它保證平衡性的一些特性:
這些約束確保了紅黑樹的關鍵特性:從根到葉子的最長路徑很少於最短路徑的兩倍長(根據性質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樹 又稱前綴樹或字典樹,它是一種專門處理字符串匹配的數據結構,用來解決在一組字符串集合中快速查找某個字符串的問題。
它的特性爲:
若是咱們有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+樹、LSM Tree是數據庫中常常出現的數據結構。對於數據庫的增刪改查效率,須要考慮的首要因素是:磁盤的IO訪問次數。
如何減小IO訪問次數?
前文咱們已經提到了索引,可是IO一次不容易,從磁盤中獲取數據一般是以塊爲單位的。若是對於上千萬條數據,咱們只創建一層索引結構的話,那索引的數據量也是巨大的。
如何下降索引量?
假設咱們到全世界找一我的,咱們是按照 國家/省/市/區/街道/小區的順序來定位。同理,隨着數據量的增大,咱們須要一層層的創建 多級索引 。越上層的索引每一個塊中表示的數據範圍越大。
如何保證咱們創建的多級索引 是「合適」的?
這個合適主要指:存儲的數據量大而且樹高小。同紅黑樹同樣,咱們須要一些 限制條件 來保證樹高。這也就是如下數據結構的限制條件緣由了。
一個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
一個m階的B+樹具備如下特徵:
1.有k個子樹的中間節點包含有k個元素(B樹中是k-1個元素),每一個元素不保存數據,只用來索引,全部數據都保存在葉子節點。
2.全部的葉子節點中包含了所有元素的信息,及指向含這些元素記錄的指針,且葉子節點自己依關鍵字的大小自小而大順序連接。
3.全部的中間節點元素都同時存在於子節點,在子節點元素中是最大(或最小)元素。
看不懂不要緊,咱們只須要知道這些限制條件是爲了讓B+樹數據「矮而胖」就好。
這裏我直接放張掘金小冊《從根兒上理解MYSQL》B+樹主鍵索引的示意圖:
應用場景
1.Mysql InnoDB存儲引擎。
看到這裏常考面試題來了:B樹和B+樹有什麼區別?爲何Mongo用B樹?爲何Mysql用B+樹?
看圖說話,B樹 和 B+樹顯著不一樣的地方是:
1.B樹非葉子節點便是索引,也是數據;B+樹非葉子節點僅是索引,數據所有存儲在葉子節點。
2.B+樹葉子節點的數據之間是用鏈表連接的。
這會致使:
B+樹相比B樹:
1.數據的連續性:
2.葉子結點之間的鏈接性:
B樹相比B+樹:
看成單一數據查詢時,B樹的結點平均離根結點更近,平均查詢效率比B+樹快。
總結一下:B+樹相比B樹,前者更適合範圍查詢,後者更適合單一數據查詢。
Mongo是非關係型數據庫,數據之間的關係用嵌套解決。它的主要使用場景是: 追求 單個讀寫記錄的性能。
Mysql是關係型數據庫,數據之間的關係用共同的索引鍵,Join解決。它的使用場景:不只存在大量的單一數據查詢,也存在大量的範圍查詢。
因此上面的問題能夠簡單扯一扯了吧。
下篇文章233醬準備介紹近幾年數據庫中常常出現的角色:LSM Tree。以爲本文有收穫 or 期待下篇 請四連【關注,點贊,在看,轉發】支持下233吧~
參考資料:
[1].維基百科
[2].https://www.youtube.com/watch?v=OJ5NYq1Eii8
[3].https://time.geekbang.org/column/article/72414
[4].https://towardsdatascience.com/8-useful-tree-data-structures-worth-knowing-8532c7231e8c
[5].https://draveness.me/whys-the-design-mongodb-b-tree/