常见树的总结
樹
BST
Binary Sort Tree:二叉查找樹,或二叉搜索樹,或二叉排序樹
性質:
若左子樹不空,則左子樹上所有結點的值均小于它的根結點的值;
若右子樹不空,則右子樹上所有結點的值均大于或等于它的根結點的值;
左、右子樹也分別為二叉查找樹;
沒有鍵值相等的節(jié)點。
**特點:**對二叉查找樹的中序遍歷,是升序的序列。查找的時間復雜度 O(logN),最壞的情況下退化至O(N),因此出現(xiàn)了各種平衡二叉樹,以最求優(yōu)雅的O(logN)。
二叉查找樹的插入過程如下:
若當前的二叉查找樹為空,則插入的元素為根節(jié)點;
若插入的元素值小于根節(jié)點值,則將元素插入到左子樹中;
若插入的元素值不小于根節(jié)點值,則將元素插入到右子樹中。
AVL
平衡二叉樹:(Balanced Binary Tree),平衡的BST,以發(fā)明人命名,AVL(Adelson-Velskii and Landis)
性質:如果每一個節(jié)點的左子樹和右子樹的高度差不超過1,那么這可樹就是平衡二叉樹。
特點:判斷一個樹是否為平衡樹,把握三點。遞歸判斷 (1)左子樹是否平衡 (2)右子樹是否平衡 (3)左子樹的高度和右子樹的高度差值低于1。查找的時間復雜度,嚴格的O(logN)。優(yōu)雅的解決了BST退化成鏈表的問題,把插入,查找,刪除的時間復雜度最好情況和最壞情況都維持在O(logN)。
缺點:頻繁旋轉會使插入和刪除犧牲掉O(logN)左右的時間,不過相對BST來說,時間上穩(wěn)定了很多。
自平衡操作:4種情況的失衡狀態(tài),兩兩對稱
1)LL型:如果在一個節(jié)點的左子樹的左子樹上插入一個新節(jié)點。方法:將節(jié)點右旋使其平衡。
? 原A的左孩子B變?yōu)楦附Y點,A變?yōu)槠溆液⒆樱瑽的右子樹變?yōu)锳的左子樹,注意旋轉之后Brh是A的左子樹。
2)RR型:在一個節(jié)點的右子樹的右子樹上插入一個新節(jié)點。方法:將節(jié)點左旋使其平衡。
? 原A右孩子B變?yōu)楦附Y點,A變?yōu)槠渥蠛⒆樱瑽的左子樹Blh將變?yōu)锳的右子樹。
3)LR型:在一個節(jié)點的左子樹的右子樹上插入一個新節(jié)點。方法:雙旋轉,兩步走,先讓樹中高度較低的進行一次左旋,這個時候就變成了LL型了。再進行一次右旋操作即可。
在B節(jié)點按照RR型向左旋轉一次之后,二叉樹在A節(jié)點仍然不能保持平衡,這時還需要再向右旋轉一次。
4)RL型:在一個節(jié)點的右子樹的左子樹上插入一個新節(jié)點。方法:雙旋轉,先讓樹中高度較低的進行一次右旋,這個時候就變成了RR型了。再進行一次左旋操作即可。
與LR情況剛好相反,將B結點右旋,變?yōu)镽R,再讓A結點單左旋。
R-B Tree
紅黑樹:是一種自平衡二叉查找樹,復雜且高效,并且在實踐中是高效的: 它可以在O(logn)時間內做查找,插入和刪除。紅黑樹還是2-3-4樹的一種等同,它們的思想是一樣的,只不過紅黑樹是2-3-4樹用二叉樹的形式表示的。
性質:五大性質
1)所有節(jié)點都是 紅色 或者 黑色,非紅即黑。
2)根節(jié)點是黑色
3)紅色節(jié)點的子節(jié)點不能是紅色,必須是黑色
4)所有的NIL結點都是黑色(注:為空的葉子節(jié)點)
5)從任意節(jié)點出發(fā),所有到NIL節(jié)點的路徑含有相同數(shù)量的黑色節(jié)點
如下圖所示:
紅黑樹基本操作(一):添加節(jié)點
? 大致步驟,將紅黑樹當作一顆二叉查找樹,將節(jié)點插入;然后,將節(jié)點著色為紅色;最后通過旋轉和重新著色等方法,來修正,使之成為一顆滿足五大性質的紅黑樹。
? 可分為三大情況來處理:
情況1:插入節(jié)點的是根節(jié)點。方法:直接把這個節(jié)點涂為黑色
情況2:插入節(jié)點的的父節(jié)點是黑色。方法:無任何操作,仍是紅黑樹。
情況3:插入結點的父節(jié)點是紅色,又分為三種小情況:
case 1)情況:當前節(jié)點的父節(jié)點是紅色,叔叔節(jié)點也是紅色。 方法:1、將“父節(jié)點”設為黑色。2、將“叔叔節(jié)點”設為黑色。3、將“祖父節(jié)點”設為紅色。4、將“祖父節(jié)點”設為“當前節(jié)點”;即,之后的操作,繼續(xù)轉化為對“當前節(jié)點”的操作。
case 2)情況:當前節(jié)點的父節(jié)點是紅色,叔叔節(jié)點是黑色,且當前節(jié)點是其父節(jié)點的右孩子
? 方法:1、將“父節(jié)點”作為“新的當前節(jié)點”。2、以”新的當前節(jié)點“為支點進行左旋。
case 3)情況:當前節(jié)點的父節(jié)點是紅色,叔叔節(jié)點是黑色,且當前節(jié)點是其父節(jié)點的左孩子
? 方法:1、將“父節(jié)點”設為黑色。2、將“祖父節(jié)點”設為紅色。3、以“祖父節(jié)點”為支點進行右旋
紅黑樹的基本操作(二):刪除
? 大致步驟,將紅黑樹當作一顆二叉查找樹,將該節(jié)點從二叉查找樹中刪除;然后,通過旋轉和重新著色等操作來修復成紅黑樹,使之重新成為一顆紅黑樹。
? 第一步:
情況1:被刪除的節(jié)點沒有孩子,即為葉節(jié)點(注:不是NIL節(jié)點)。方法:直接刪除該節(jié)點
情況2:被刪除的節(jié)點只有一個孩子。方法:直接刪除該節(jié)點,那么該孩子直接頂替它的位置。
情況3:被刪除的節(jié)點有兩個孩子。則找到“當前節(jié)點”的“后繼節(jié)點”,把“后繼節(jié)點”復制給“當前節(jié)點”,覆蓋它。然后刪除后繼節(jié)點。即問題往下轉移,直至遇到情況1,和情況2,停止。
? 第二步:
? 修復紅黑樹,通過旋轉和重新著色,使之重新成為一顆紅黑樹。
B-tree
B-tree即B樹,B-樹,又叫平衡多路查找樹。
一顆m階的B樹(m叉樹)的特性如下:
1、樹中每個節(jié)點最多含有m個孩子;
2、除根節(jié)點和葉子結點外,其他每個節(jié)點至少有[ceil(m/2)]個孩子(其中ceil(x)是一個取上限的函數(shù));
3、若根節(jié)點不是葉子結點,則至少有兩個孩子(特例:整棵樹只有一個節(jié)點);
4、所有的葉子結點都出現(xiàn)在同一層,葉子結點為NULL,即NIL節(jié)點;
5、有j個孩子的非葉節(jié)點恰好有j-1個關鍵碼,關鍵碼按遞增次序排列;
備注:B樹中的每個結點根據(jù)實際情況可以包含大量的關鍵字信息和分支(當然是不能超過磁盤塊的大小,根據(jù)磁盤驅動(disk drives)的不同,一般塊的大小在1k~4k左右);這樣樹的深度降低了,這就意味著查找一個元素只要很少結點從外存磁盤中讀入內存,很快訪問到要查找的數(shù)據(jù)。
B+tree
B+樹,是應文件系統(tǒng)所需而產生的一種B-tree的變形樹。
與B樹的差異在于:
1、有n棵子樹的節(jié)點含有n個關鍵字;(而B樹是n棵子樹有n-1個關鍵字)
2、所有葉子結點中包含了全部關鍵字的信息,即指向含有這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小,自小到大的順序鏈接。(而B樹的葉子節(jié)點并沒有包括全部需要查找的信息)
3、所有的非終端節(jié)點可以看成是索引部分,節(jié)點中僅含有其子樹根節(jié)點中最大(或最小的關鍵字)。而B樹的非葉子結點也包含需要查找的有效信息。
問題: 為什么說B±tree比B 樹更適合實際應用中操作系統(tǒng)的文件索引和數(shù)據(jù)庫索引?
B±tree的磁盤讀寫代價更低
B±tree的內部結點并沒有指向關鍵字具體信息的指針。因此其內部結點相對B 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那么盤塊所能容納的關鍵字數(shù)量也越多。一次性讀入內存中的需要查找的關鍵字也就越多。相對來說IO讀寫次數(shù)也就降低了。
? 舉個例子,假設磁盤中的一個盤塊容納16bytes,而一個關鍵字2bytes,一個關鍵字具體信息指針2bytes。一棵9階B-tree(一個結點最多8個關鍵字)的內部結點需要2個盤快。而B+ 樹內部結點只需要1個盤快。當需要把內部結點讀入內存中的時候,B 樹就比B+ 樹多一次盤塊查找時間(在磁盤中就是盤片旋轉的時間)。
B±tree的查詢效率更加穩(wěn)定
由于非終結點并不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數(shù)據(jù)的查詢效率相當。
SB-Tree
SB-Tree:Size Balanced Tree,自平衡條件:每個結點所在子樹的結點個數(shù)不小于其兄弟的兩個孩子所在子樹的結點個數(shù)。
與AVL樹的差異:
? AVL 樹比較的是層數(shù),而SB 樹比較的是 Size ,結點的多少。另一個和 AVL 不太一樣的是,SBTree 只有在插入時才可能觸發(fā)調整,而不需要在刪除結點以后進行調整。
插入時的調整:與AVL樹類似,分為LL,RR,LR,RL,四種情況。
TireTree
字典樹,又稱前綴樹解決字符串前綴匹配問題,查找單詞是否存在,統(tǒng)計以如“abc”開始的字符串的個數(shù),實現(xiàn)詞頻統(tǒng)計等。
public static class TrieNode {
public int path; // 記錄有多少個字符經(jīng)過
public int end; // 記錄有多少個字符串以此節(jié)點結尾
public TrieNode[] nexts; // 路
public TrieNode() {
path = 0;
end = 0;
nexts = new TrieNode[26];
}
}
總結
- 上一篇: EMC存储产品分析介绍 (一)
- 下一篇: 闻酥园与宫廷糕点的桃酥对比