二叉搜索樹
二叉搜索樹(Binary Search Tree,簡寫B(tài)ST),又稱為二叉排序樹,屬于樹的一種,通過二叉樹將數(shù)據(jù)組織起來,樹的每個節(jié)點都包含了健值 key、數(shù)據(jù)值 data、左子節(jié)點指針、右子節(jié)點指針。其中健值 key 是最核心的部分,它的值決定了樹的組織形狀;數(shù)據(jù)值 data 是該節(jié)點對應的數(shù)據(jù),有些場景可以忽略,舉個例子,key 為身份證號而 data 為人名,通過身份證號找人名;左子節(jié)點指針指向左子節(jié)點;右子節(jié)點指針指向右子節(jié)點。
二叉搜索樹特點
- 左右子樹也分別是二叉搜索樹。
- 左子樹的所有節(jié)點 key 值都小于它的根節(jié)點的 key 值。
- 右子樹的所有節(jié)點 key 值都大于他的根節(jié)點的 key 值。
- 二叉搜索樹可以為一棵空樹。
- 一般來說,樹中的每個節(jié)點的 key 值都不相等,但根據(jù)需要也可以將相同的 key 值插入樹中。
AVL樹
AVL樹,也稱平衡二叉搜索樹,AVL是其發(fā)明者姓名簡寫。AVL樹屬于樹的一種,而且它也是一棵二叉搜索樹,不同的是他通過一定機制能保證二叉搜索樹的平衡,平衡的二叉搜索樹的查詢效率更高。
AVL樹特點
- AVL樹是一棵二叉搜索樹。
- AVL樹的左右子節(jié)點也是AVL樹。
- AVL樹擁有二叉搜索樹的所有基本特點。
- 每個節(jié)點的左右子節(jié)點的高度之差的絕對值最多為1,即平衡因子為范圍為[-1,1]。
紅黑樹
紅黑(Red-black)樹是一種自平衡二叉查找樹,1972年由Rudolf Bayer發(fā)明,它與AVL樹類似,都在插入和刪除操作時能通過旋轉(zhuǎn)操作保持二叉查找樹的平衡,以便能獲得高效的查找性能。
它可以在 O(logn) 時間內(nèi)做查找,插入和刪除等操作。紅黑樹是2-3-4樹的一種等同,但有些紅黑樹設定只能左邊是紅樹,這種情況就是2-3樹的一種等同了。
對于AVL樹來說,紅黑樹犧牲了部分平衡性以換取插入/刪除操作時少量的旋轉(zhuǎn)操作,整體來說性能要優(yōu)于AVL樹。
紅黑樹性質(zhì)
- 節(jié)點是紅色或黑色。
- 根節(jié)點是黑色。
- 每個葉節(jié)點(NIL節(jié)點)是黑色的。
- 每個紅色節(jié)點的兩個子節(jié)點都為黑色。(從每個葉子到根的所有路徑上不能有兩個連續(xù)的紅色節(jié)點)
- 從任一節(jié)點到其每個葉子的所有路徑都包含相同數(shù)目的黑色節(jié)點。
2-3樹
2-3樹,是最簡單的B-樹,其中2、3主要體現(xiàn)在每個非葉子節(jié)點都有2個或3個子節(jié)點,B-樹即是平衡樹,平衡樹是為了解決不平衡樹查詢效率問題,常見的二叉平衡書有AVL樹,它雖然提高了查詢效率,但是插入操作效率不高,因為它需要再每次插入節(jié)點后維護樹的平衡,而為了解決查詢效率同時有兼顧插入效率,于是提出了2-3樹。
2-3樹特點
- 2-3樹是一棵平衡樹,但不是二叉平衡樹。
- 對于高度相同的2-3樹和二叉樹,2-3樹的節(jié)點數(shù)要大于滿二叉樹,因為有些節(jié)點可能有三個子節(jié)點。
- 2-3樹可以是一棵空樹。
- 對于2節(jié)點來說,該節(jié)點保存了一個key及對應的value,除此之外還保存了指向左右兩邊的子節(jié)點,子節(jié)點也是一個2-3節(jié)點,左子節(jié)點所有值小于key,右子節(jié)點所有值大于key。
- 對于3節(jié)點來說,該節(jié)點保存了兩個key及對應的value,除此之外還保存了指向左中右三個方向的子節(jié)點,子節(jié)點也是一個2-3節(jié)點,左子節(jié)點的所有值小于兩個key中較小的那個,中節(jié)點的所有值在兩個key值之間,右子節(jié)點大于兩個key中較大的那個。
- 對2-3樹進行中序遍歷能得到一個排好序的序列。
B樹
B樹即平衡查找樹,一般理解為平衡多路查找樹,也稱為B-樹、B_樹。是一種自平衡樹狀數(shù)據(jù)結(jié)構,能對存儲的數(shù)據(jù)進行O(log n)的時間復雜度進行查找、插入和刪除。B樹一般較多用在存儲系統(tǒng)上,比如數(shù)據(jù)庫或文件系統(tǒng)。
B樹特點
- B樹可以定義一個m值作為預定范圍,即m路(階)B樹。
- 每個節(jié)點最多有m個孩子。
- 每個節(jié)點至少有ceil(m/2)個孩子,除了根節(jié)點和葉子節(jié)點外。
- 對于根節(jié)點,子樹個數(shù)范圍為[2,m],節(jié)點內(nèi)值的個數(shù)范圍為[1,m-1]。
- 對于非根節(jié)點,節(jié)點內(nèi)的值個數(shù)范圍為[ceil(m/2)-1,m-1]。
- 根節(jié)點(非葉子節(jié)點)至少有兩個孩子。
- 一個有k個孩子的非葉子節(jié)點包含k-1個值。
- 所有葉子節(jié)點在同一層。
- 節(jié)點內(nèi)的值按照從小到大排列。
- 父節(jié)點的若干值作為分離值分成多個子樹,左子樹小于對應分離值,對應分離值小于右子樹。
B+樹
B+樹是B樹的一種變體,也屬于平衡多路查找樹,大體結(jié)構與B樹相同,包含根節(jié)點、內(nèi)部節(jié)點和葉子節(jié)點。多用于數(shù)據(jù)庫和操作系統(tǒng)的文件系統(tǒng)中,由于B+樹內(nèi)部節(jié)點不保存數(shù)據(jù),所以能在內(nèi)存中存放更多索引,增加緩存命中率。另外因為葉子節(jié)點相連遍歷操作很方便,而且數(shù)據(jù)也具有順序性,便于區(qū)間查找。
B+樹特點
- B+樹可以定義一個m值作為預定范圍,即m路(階)B+樹。
- 根節(jié)點可能是葉子節(jié)點,也可能是包含兩個或兩個以上子節(jié)點的節(jié)點。
- 內(nèi)部節(jié)點如果擁有k個關鍵字則有k+1個子節(jié)點。
- 非葉子節(jié)點不保存數(shù)據(jù),只保存關鍵字用作索引,所有數(shù)據(jù)都保存在葉子節(jié)點中。
- 非葉子節(jié)點有若干子樹指針,如果非葉子節(jié)點關鍵字為k1,k2,...kn,其中n=m-1,那么第一個子樹關鍵字判斷條件為小于k1,第二個為大于等于k1而小于k2,以此類推,最后一個為大于等于kn,總共可以劃分出m個區(qū)間,即可以有m個分支。(判斷條件其實沒有嚴格的要求,只要能實現(xiàn)對B+樹的數(shù)據(jù)進行定位劃分即可,有些實現(xiàn)使用了m個關鍵字來劃分區(qū)間,也是可以的)
- 所有葉子節(jié)點通過指針鏈相連,且葉子節(jié)點本身按關鍵字的大小從小到大順序排列。
- 自然插入而不進行刪除操作時,葉子節(jié)點項的個數(shù)范圍為[floor(m/2),m-1],內(nèi)部節(jié)點項的個數(shù)范圍為[ceil(m/2)-1,m-1]。
- 另外通常B+樹有兩個頭指針,一個指向根節(jié)點一個指向關鍵字最小的葉子節(jié)點。
- 在進行刪除操作時,涉及到索引節(jié)點填充因子和葉子節(jié)點填充因子,一般可設葉子節(jié)點和索引節(jié)點的填充因子都不少于50%。
關于LSM樹
LSM樹,即日志結(jié)構合并樹(Log-Structured Merge-Tree)。其實它并不屬于一個具體的數(shù)據(jù)結(jié)構,它更多是一種數(shù)據(jù)結(jié)構的設計思想。大多NoSQL數(shù)據(jù)庫核心思想都是基于LSM來做的,只是具體的實現(xiàn)不同。
LSM樹誕生背景
傳統(tǒng)關系型數(shù)據(jù)庫使用btree或一些變體作為存儲結(jié)構,能高效進行查找。但保存在磁盤中時它也有一個明顯的缺陷,那就是邏輯上相離很近但物理卻可能相隔很遠,這就可能造成大量的磁盤隨機讀寫。隨機讀寫比順序讀寫慢很多,為了提升IO性能,我們需要一種能將隨機操作變?yōu)轫樞虿僮鞯臋C制,于是便有了LSM樹。LSM樹能讓我們進行順序?qū)懘疟P,從而大幅提升寫操作,作為代價的是犧牲了一些讀性能。
關于磁盤IO
磁盤讀寫時涉及到磁盤上數(shù)據(jù)查找,地址一般由柱面號、盤面號和塊號三者構成。也就是說移動臂先根據(jù)柱面號移動到指定柱面,然后根據(jù)盤面號確定盤面的磁道,最后根據(jù)塊號將指定的磁道段移動到磁頭下,便可開始讀寫。
整個過程主要有三部分時間消耗,查找時間(seek time) +等待時間(latency time)+傳輸時間(transmission time) 。分別表示定位柱面的耗時、將塊號指定磁道段移到磁頭的耗時、將數(shù)據(jù)傳到內(nèi)存的耗時。整個磁盤IO最耗時的地方在查找時間,所以減少查找時間能大幅提升性能。
Radix樹
Radix樹,即基數(shù)樹,也稱壓縮前綴樹,是一種提供key-value存儲查找的數(shù)據(jù)結(jié)構。與Trie不同的是,它對Trie樹進行了空間優(yōu)化,只有一個子節(jié)點的中間節(jié)點將被壓縮。同樣的,Radix樹的插入、查詢、刪除操作的時間復雜度都為O(k)。
Radix樹特點
一般由根節(jié)點、中間節(jié)點和葉子節(jié)點組成。
每個節(jié)點可以包含一個或多個字符。
樹的葉子結(jié)點數(shù)即是數(shù)據(jù)條目數(shù)。
從根節(jié)點到某一節(jié)點經(jīng)過路徑的字符連起來即為該節(jié)點對應的字符串。
每個節(jié)點的所有子節(jié)點字符串都不相同