1. 程式人生 > 實用技巧 >常見的二叉樹

常見的二叉樹

常見的二叉樹

以下的二叉樹採用的結構都為鏈式結構

typedef  struct BiTNode    /* 結點結構 */
{
    int data;    /* 結點資料 */
    struct BiTNode *lchild, *rchild; /* 左右孩子指標 */
} BiTNode, *BiTree;

1. 二叉排序樹

二叉排序樹又稱“二叉查詢樹”、“二叉搜尋樹”。

定義

或者是一棵空樹,或者是具有下列性質的二叉樹:

  1. 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;

  2. 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;

  3. 它的左、右子樹也分別為二叉排序樹。

中序遍歷二叉排序樹可得到一個依據關鍵字的有序序列,一個無序序列可以通過構造一棵二叉排序樹變成一個有序序列,構造樹的過程即是對無序序列進行排序的過程。每次插入的新的結點都是二叉排序樹上新的葉子結點,在進行插入操作時,不必移動其它結點,只需改動某個結點的指標,由空變為非空即可。搜尋、插入、刪除的時間複雜度等於樹高,期望O(logn),最壞O(n)(數列有序,樹退化成線性表,如右斜樹)。

查詢演算法

查詢過程:

1.若b是空樹,則搜尋失敗,否則:

2.若x等於b的根節點的資料域之值,則查詢成功;否則:

3.若x小於b的根節點的資料域之值,則搜尋左子樹;否則:

4.查詢右子樹。

5.若查詢不成功, 則指標 p 指向查詢路徑上訪問的最後一個結點並返回FALSE

插入演算法

插入過程:

  1. 先呼叫查詢操作將要插入的關鍵字進行比較

  2. 如果在原有的二叉排序樹中沒有要插入的關鍵字,則將關鍵字與查詢的結點p(在查詢操作中返回的結點)的值進行比較

  3. 若p為空,則插入關鍵字賦值給該節點;

  4. 若小於結點p的值,則插入關鍵字作為結點p的左子樹;

  5. 若大於結點p的值,則插入關鍵字作為結點p的右子樹;

每次需要插入的節點都為葉子節點。

刪除演算法

刪去一個結點,分三種情況討論:

  1. 若*p結點為葉子結點,即PL(左子樹)和PR(右子樹)均為空樹。由於刪去葉子結點不破壞整棵樹的結構,則只需修改其雙親結點的指標即可。

  2. p結點只有左子樹PL或右子樹PR,此時只要令PL或PR直接成為其雙親結點

    f的左子樹(當p是左子樹)或右子樹(當p是右子樹)即可,作此修改也不破壞二叉排序樹的特性。

  3. p結點的左子樹和右 子樹均不空。在刪去p之後,為保持其它元素之間的相對位置不變,可按中序遍歷保持有序進行調整。比較好的做法是,找到p的直接前驅(或直接後繼)s,用s來替換結點p,然後再刪除結點*s。(依靠中序遍歷在p節點下進行遍歷得到的最後一個數即為替換的節點)

效能分析

  • 最好的情況是二叉排序樹的形態和折半查詢的判定樹相同,其平均查詢長度和logn成正比(O(log2(n)))。
  • 最壞情況下,當先後插入的關鍵字有序時,構成的二叉排序樹為一棵斜樹,樹的深度為n,其平均查詢長度為(n + 1) / 2。也就是時間複雜度為O(n),等同於順序查詢。

雖然二叉排序樹的最壞效率是O(n),但它支援動態查詢。最好是把它構建成一棵平衡的二叉排序樹(平衡二叉樹),這些平衡二叉樹可以使樹高為O(logn),如AVL、紅黑樹等。

2. 平衡二叉樹(AVL)

定義

它或者是一顆空樹,或者具有以下性質的二叉樹:它的左子樹和右子樹的深度之差的絕對值不超過1,且它的左子樹和右子樹都是一顆平衡二叉樹。

平衡因子(bf):結點的左子樹的深度減去右子樹的深度,那麼顯然-1<=bf<=1;

在AVL樹中,任一節點對應的兩棵子樹的最大高度差為1,因此它也被稱為高度平衡樹

查詢、插入和刪除在平均和最壞情況下的時間複雜度都是$O(log(n))$。增加和刪除元素的操作則可能需要藉由一次或多次樹旋轉,以實現樹的重新平衡。

查詢操作

平衡二叉樹的查詢基本與二叉查詢樹相同。

插入操作

在平衡二叉樹中插入結點與二叉查詢樹最大的不同在於要隨時保證插入後整棵二叉樹是平衡的。那麼調整不平衡樹的基本方法就是: 旋轉 。

首先,還需要明白的一個概念就是:

最小不平衡子樹的根結點:也就是當你進行插入操作時,找到該需要插入結點的位置並插入後,從該結點起向上尋找(回溯),第一個不平衡的結點即平衡因子bf變為-2或2的節點。

那究竟是如何“轉”的呢?

其實,可以換一種思路思考,不讓它叫“旋轉”!而叫——>“兩個結點的變換”

下面分情況分析四種旋轉方式

左左

即在x的左孩子a的左孩子c上插入一個結點y(該結點也可以是c,如圖①),即y可以是c,也可以是c的左孩子(如圖②),也可以是c的右孩子(不在畫出)

這種左左插入方式有一個規律:不平衡子樹的左子樹深度比右子樹深度大2.

圖①②插入的節點都為y,此時向上回溯第一個不平衡的子樹根節點為x,那麼將x節點及其右子樹(圖①為NULL,圖②為b)一起繞著x的左子樹根節點(即a)右旋(即順時針旋轉),然後將a的右子樹作為x的左子樹,假如a的右子樹為空則不必插入。那麼這樣旋轉最後將不平衡子樹變為平衡。

右右

即在x的右孩子a的右孩子c上插入一個結點y(該結點也可以是c,如圖①),即y可以是c,也可以是c的右孩子(如圖②),也可以是c的左孩子(不在畫出)

這種右右插入方式有一個規律:不平衡子樹的左子樹深度比右子樹深度小2.

圖①②插入的節點都為y,此時向上回溯找到第一個不平衡子樹的節點為x,需要將節點x及其左子樹(圖①為NULL,圖二為b)繞著x右子樹(兩圖都為a為根節點的子樹)進行左旋(逆時針旋轉),然後將其右子樹(a)的左節點作為x的右節點,這樣使得不平衡子樹又再度平衡。

左右

即在x的左孩子a的右孩子c上插入一個結點y(該結點也可以是c,如圖①),即y可以是c,也可以是c的右孩子(如圖②),也可以是c的左孩子(不在畫出)

這種左右插入的規律就是:不平衡子樹的左子樹高度比右子樹大2且左子樹的右子樹比左子樹的左子樹深度深。

向上回溯的第一個不平衡子樹為x,先對x的左子樹左旋(旋轉中心為c),再對x的左子樹進行右旋(旋轉中心為c)。(旋轉中心為左子樹的右節點)

如果是圖①,旋轉中心為y

右左

即在x的右孩子a的左孩子c上插入一個結點y(該結點也可以是c,如圖①),即y可以是c,也可以是c的右孩子(如圖②),也可以是c的左孩子(不在畫出)

這種右左插入的規律就是:不平衡子樹的右子樹高度比左子樹大2且右子樹的左子樹比右子樹的右子樹深度深。

向上回溯的第一個不平衡子樹為x,先對x的右子樹右旋(旋轉中心為c),再對x的右子樹進行左旋(旋轉中心為c)。(旋轉中心為左子樹的右節點)

如果是圖①,旋轉中心為y

AVL樹的操作彙總:

刪除操作

刪除類似插入的操作。刪除時少一個結點,也就是該結點所在的子樹深度可能會減小,而插入時多一個結點,該結點所在的子樹深度可能會增加,所以遞迴刪除一個結點時,回溯時找到最小不平衡子樹的根結點時,要向相反的方向去找屬於哪種情況;

如圖y為要刪除的節點

圖①:y結點刪除後,回溯到x結點從bf=-1變為bf=-2;則需從相反方向即從x的右孩子的方向向下檢查屬於哪種情況,顯然第一個方向為1:右;第二個方向看a的bf的值——若為1時,那就相當於插入時‘右左’的情況;若為-1時,那就相當於插入時‘右右’的情況;可現在a的bf既不是1也不是-1而是0,這就是刪除的特殊情況了!我們不妨試試對他進行類似於插入時的‘右右’操作,看怎麼樣~ 如上圖,經過變換後該子樹平衡了!但是因子的修改就跟插入時的‘右右’不一樣了!此時變為:x的bf=-1,a的bf=1;所以我們不妨就把a的bf=0也歸納為刪除的‘右右’或‘左左’(如圖②,不再敖述)操作;

那麼刪除時因子的改變需在插入時因子的改變中新增上:

左左:前a:bf=0 後x:bf=1,a:bf=-1; 右右:前a:bf=0 後x:bf=-1,a:bf=1;其他不變!

可以想象,其實是很簡單的道理:除了特殊情況其他都與插入的情況一模一樣,說白了就是把深度大的子樹(根結點的其中一個)向深度小子樹貢獻一個深度,那麼這樣一來,該子樹(對於根結點所領導的樹)的深度是不是比原來的小1了?!所以要繼續向上一個一個進行檢索,直到根結點為止!

程式碼實現

https://blog.csdn.net/nightwizard2030/article/details/72874715

效能分析

優勢

平衡二叉樹的優勢在於不會出現普通二叉查詢樹的最差情況。其查詢的時間複雜度為$O(logN)$。

缺陷

  1. 為了保證高度平衡,動態插入和刪除的代價也隨之增加.
  2. 所有二叉查詢樹結構的查詢代價都與樹高是緊密相關的,能否通過減少樹高來進一步降低查詢代價呢。

應用場景

應用:windows對程序地址空間的管理用到了AVL樹。

3. 紅黑樹

也被稱為"對稱二叉B樹"。

定義

紅黑樹(red-black tree) 是一棵滿足下述性質的二叉查詢樹:

  1. 每一個結點要麼是紅色,要麼是黑色。

  2. 根結點是黑色的。

  3. 所有葉子結點都是黑色的(實際上都是Null指標,下圖用NIL表示)。葉子結點不包含任何關鍵字資訊,所有查詢關鍵字都在非終結點上。

  4. 每個紅色結點的兩個子節點必須是黑色的。換句話說:從每個葉子到根的所有路徑上不能有兩個連續的紅色結點

  5. 從任一結點到其每個葉子的所有路徑都包含相同數目的黑色結點

幾個概念:

黑深度 ——從某個結點x出發(不包括結點x本身)到葉結點(包括葉子結點)的路徑上的黑結點個數,稱為該結點x的黑深度,記為$bd(x)$,根結點的黑深度就是該紅黑樹的黑深度。葉子結點的黑深度為0。比如:上圖$bd(13)=2, bd(8)=2, bd(1)=1$

內部結點 —— 紅黑樹的非終結點

外部節點 —— 紅黑樹的葉子結點

相關原理

  1. 從根到葉子的最長的可能路徑不多於最短的可能路徑的兩倍長。
  2. 紅黑樹的樹高$(h)$不大於兩倍的紅黑樹的黑深度$(bd)$,即$h<=2bd$
  3. 一棵擁有n個內部結點(不包括葉子結點)的紅黑樹的樹高$h<=2log(n+1)$

查詢操作

因為每一個紅黑樹也是一個特化的二叉查詢樹,因此紅黑樹上的查詢操作與普通二叉查詢樹上的查詢操作相同.

插入操作

我們首先以二叉查詢樹的方法增加節點並標記它為紅色。下面要進行什麼操作取決於其他臨近節點的顏色。同人類的家族樹中一樣,我們將使用術語叔父節點來指一個節點的父節點的兄弟節點

假設新加入的結點為N,父親結點為P,叔父結點為Ui(叔父結點就是一些列P的兄弟結點),祖父結點G(父親結點P的父親)。

情況1. 當前紅黑樹為空,新結點N位於樹的根上,沒有父結點。

此時很簡單,我們將直接插入一個黑結點N(滿足性質2),因為是特殊大的情況,不插入紅色而插入黑色節點。

情況2. 新結點N的父結點P是黑色。

在這種情況下,我們插入一個紅色結點N(滿足性質5)

注意:在情況3,4,5下,我們假定新節點有祖父節點,因為父節點是紅色;並且如果它是根,它就應當是黑色。所以新節點總有一個叔父節點,儘管在情形4和5下它可能是葉子。

情況3.如果父節點P和叔父節點U二者都是紅色。

如下圖,因為新加入的N結點必須為紅色,那麼我們可以將父結點P(保證性質4),以及N的叔父結點U(保證性質5)重新繪製成黑色。如果此時祖父結點G是根,則結束變化。如果不是根,則祖父結點重繪為紅色(保證性質5)。但是,G的父親也可能是紅色的,為了保證性質4。我們把G遞迴當做新加入的結點N在進行各種情況的重新檢查。

注意:在情形4和5下,我們假定父節點P 是祖父結點G 的左子節點。如果它是右子節點,情形4和情形5中的左和右應當對調。

情況4. 父節點P是紅色而叔父節點U是黑色或缺少; 另外,新節點N是其父節點P的右子節點,而父節點P又是祖父結點G的左子節點。

如下圖, 在這種情形下,我們進行一次左旋轉調換新節點和其父節點的角色(與AVL樹的左旋轉相同); 這導致某些路徑通過它們以前不通過的新節點N或父節點P中的一個,但是這兩個節點都是紅色的,所以性質5沒有失效。但目前情況將違反性質4,所以接著,我們按下面的情況5繼續處理以前的父節點P。

情況5. 父節點P是紅色而叔父節點U 是黑色或缺少,新節點N 是其父節點的左子節點,而父節點P又是祖父結點的G的左子節點。

如下圖: 在這種情形下,我們進行鍼對祖父節點P 的一次右旋轉; 在旋轉產生的樹中,以前的父節點P現在是新節點N和以前的祖父節點G 的父節點。我們知道以前的祖父節點G是黑色,否則父節點P就不可能是紅色。我們切換以前的父節點P和祖父節點G的顏色,結果的樹滿足性質4[3]。性質 5[4]也仍然保持滿足,因為通過這三個節點中任何一個的所有路徑以前都通過祖父節點G ,現在它們都通過以前的父節點P。在各自的情形下,這都是三個節點中唯一的黑色節點。

刪除操作

相較於插入操作,紅黑樹的刪除操作則要更為複雜一些。刪除操作首先要確定待刪除節點有幾個孩子,如果有兩個孩子,不能直接刪除該節點。而是要先找到該節點的前驅(該節點左子樹中最大的節點)或者後繼(該節點右子樹中最小的節點),然後將前驅或者後繼的值複製到要刪除的節點中,最後再將前驅或後繼刪除。由於前驅和後繼至多隻有一個孩子節點,這樣我們就把原來要刪除的節點有兩個孩子的問題轉化為只有一個孩子節點的問題,問題被簡化了一些。我們並不關心最終被刪除的節點是否是我們開始想要刪除的那個節點,只要節點裡的值最終被刪除就行了,至於樹結構如何變化,這個並不重要。

應用場景

工業界最主要使用的二叉搜尋平衡樹,廣泛用在C++的STL中。如map和set都是用紅黑樹實現的。Java用它來實現TreeMap。著名的linux程序排程Completely Fair Scheduler,用紅黑樹管理程序控制塊。

  • epoll在核心中的實現,用紅黑樹管理事件塊
  • nginx中,用紅黑樹管理timer等

Code

實現:https://www.cnblogs.com/skywang12345/p/3624291.html

紅黑樹節點定義
template <class T>
class RBTNode
{
public:
    RBTColor color;  // 顏色
    T key;           // 關鍵字(鍵值)
    RBTNode *left;   // 左孩子
    RBTNode *right;  // 右孩子
    RBTNode *parent; // 父結點

    RBTNode(T value, RBTColor c, RBTNode *p, RBTNode *l, RBTNode *r) : key(value), color(c), parent(), left(l), right(r) {}
};
顏色定義
enum RBTColor
{
    RED,
    BLACK
};

4.B樹

背景

一個比較實際的問題:就是大量資料儲存中,實現查詢這樣一個實際背景下,平衡二叉樹由於樹深度過大而造成磁碟IO讀寫過於頻繁,進而導致效率低下。那麼如何減少樹的深度(當然不能減少查詢資料量),一個基本的想法就是:

  1. 每個節點儲存多個元素 (但元素數量不能無限多,否則查詢就退化成了節點內部的線性查找了)。

  2. 摒棄二叉樹結構,採用多叉樹 (由於節點內元素數量不能無限多,自然子樹的數量也就不會無限多了)。

這樣我們就提出來了一個新的查詢樹結構 ——多路查詢樹。 根據AVL給我們的啟發,一顆平衡多路查詢樹(B~樹) 自然可以使得資料的查詢效率保證在O(logN)這樣的對數級別上。

目前大部分資料庫系統及檔案系統都採用B-Tree或其變種B+Tree作為索引結構

B-樹

B-樹是一種多路搜尋樹。

B-Tree 是滿足下列條件的資料結構:

  1. d 為大於 1 的一個正整數,稱為 B-Tree 的度。
  2. h 為一個正整數,稱為 B-Tree 的高度。
  3. 每個非葉子節點由 n-1 個 key 和 n 個指標組成,其中 d<=n<=2d。
  4. 每個葉子節點最少包含一個 key 和兩個指標,最多包含 2d-1 個 key 和 2d 個指標,葉節點的指標均為 null 。
  5. 所有葉節點具有相同的深度,等於樹高 h。
  6. key 和指標互相間隔,節點兩端是指標。
  7. 一個節點中的 key 從左到右非遞減排列。
  8. 所有節點組成樹結構。
  9. 每個指標要麼為 null,要麼指向另外一個節點。
  10. 如果某個指標在節點 node 最左邊且不為 null,則其指向節點的所有 key 小於 v(key1),其中 v(key1) 為 node 的第一個 key 的值。
  11. 如果某個指標在節點 node 最右邊且不為 null,則其指向節點的所有 key 大於 v(keym),其中 v(keym) 為 node 的最後一個 key 的值。
  12. 如果某個指標在節點 node 的左右相鄰 key 分別是 keyi 和 keyi+1 且不為 null,則其指向節點的所有 key 小於 v(keyi+1) 且大於 v(keyi)。

性質:

  1. 根結點至少有兩個子女;

  2. 每個非根節點所包含的關鍵字個數 j 滿足:┌m/2┐ - 1 <= j <= m - 1;

  3. 除根結點以外的所有結點(不包括葉子結點)的度數正好是關鍵字總數加1,故內部子樹個數 k 滿足:┌m/2┐ <= k <= m ;

  4. 所有的葉子結點都位於同一層。

用在磁碟檔案組織 資料索引和資料庫索引。

B-Tree 中的每個節點根據實際情況可以包含大量的關鍵字資訊和分支,例:

每個節點佔用一個盤塊的磁碟空間,一個節點上有兩個升序排序的關鍵字和三個指向子樹根節點的指標,指標儲存的是子節點所在磁碟塊的地址。

兩個關鍵詞劃分成的三個範圍域對應三個指標指向的子樹的資料的範圍域。

以根節點為例,關鍵字為 17 和 35,P1 指標指向的子樹的資料範圍為小於 17,P2 指標指向的子樹的資料範圍為 17~35,P3 指標指向的子樹的資料範圍為大於 35。

模擬查詢關鍵字 29 的過程:

  1. 根據根節點找到磁碟塊 1,讀入記憶體。【磁碟 I/O 操作第 1 次】
  2. 比較關鍵字 29 在區間(17,35),找到磁碟塊 1 的指標 P2。
  3. 根據 P2 指標找到磁碟塊 3,讀入記憶體。【磁碟 I/O 操作第 2 次】
  4. 比較關鍵字 29 在區間(26,30),找到磁碟塊 3 的指標 P2。
  5. 根據 P2 指標找到磁碟塊 8,讀入記憶體。【磁碟 I/O 操作第 3 次】
  6. 在磁碟塊 8 中的關鍵字列表中找到關鍵字 29。

B-Tree 相對於 AVLTree 縮減了節點個數,使每次磁碟 I/O 取到記憶體的資料都發揮了作用,從而提高了查詢效率。

B+樹

B+樹是B-樹的變體,也是一種多路搜尋樹:

1.其定義基本與B-樹同,除了:

2.非葉子結點的子樹指標與關鍵字個數相同;

3.非葉子結點的子樹指標P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹

(B-樹是開區間);

5.為所有葉子結點增加一個鏈指標;

6.所有關鍵字都在葉子結點出現;

用在磁碟檔案組織 資料索引和資料庫索引。MySQL常用的引擎InnoDB 和 Myisam 都是用 B+Tree 來儲存資料的。

B和B+主要用在檔案系統以及資料庫中做索引等,比如Mysql:B-Tree Index in MySql

在 B-Tree 中,每個節點中有 key,也有 data,而每一個頁的儲存空間是有限的,如果 data 資料較大時將會導致每個節點(即一個頁)能儲存的 key 的數量很小。當儲存的資料量很大時同樣會導致 B-Tree 的深度較大,增大查詢時的磁碟 I/O 次數,進而影響查詢效率。

B+Tree 是在 B-Tree 基礎上的一種優化,使其更適合實現外儲存索引結構,InnoDB 儲存引擎就是用 B+Tree 實現其索引結構。

B+Tree 在 B-Tree 的基礎上有兩點變化:

  1. 資料是存在葉子節點中的;
  2. 資料節點之間是有指標指向的。

由於 B+Tree 的非葉子節點只儲存鍵值資訊,假設每個磁碟塊能儲存 4 個鍵值及指標資訊,則變成 B+Tree 後其結構如下圖所示:

MySQL應用

我們通常所說的在某個欄位上建索引,意思就是讓 MySQL 對該欄位以索引這種資料結構來儲存,然後查詢的時候就有對應的查詢演算法。

建索引的根本目的是為了查詢的優化,特別是當資料很龐大的時候,一般的查詢演算法有順序查詢、折半查詢、快速查詢等。

  1. InnoDB
    InnoDB 的儲存檔案有兩個,字尾名分別是 .frm 和 .idb,其中 .frm 是表的定義檔案,而 idb 是資料檔案。

InnoDB 中存在表鎖和行鎖,不過行鎖是在命中索引的情況下才會起作用。

InnoDB 支援事務,且支援四種隔離級別(讀未提交、讀已提交、可重複讀、序列化),預設的為可重複讀;而在 Oracle 資料庫中,只支援序列化級別和讀已提交這兩種級別,其中預設的為讀已提交級別。

InnoDB 通過 B+Tree 結構對 ID 建索引,然後在葉子節點中儲存記錄。

  1. Myisam
    Myisam 的儲存檔案有三個,字尾名分別是 .frm、.MYD、MYI,其中 .frm 是表的定義檔案,.MYD 是資料檔案,.MYI 是索引檔案。

Myisam 只支援表鎖,且不支援事務。Myisam 由於有單獨的索引檔案,在讀取資料方面的效能很高 。

由於 Myisam 中的索引和資料分別存放在不同的檔案,所以在索引樹中的葉子節點中存的資料是該索引對應的資料記錄的地址,由於資料與索引不在一起,所以 Myisam 是非聚簇索引。

紅黑樹和多路查詢樹都是屬於深度有界查詢樹(depth-bounded tree —DBT)

2-3-4樹

2-3-4 樹電腦科學中是階為 4 的B樹

2-3-4 樹把資料儲存在叫做元素的單獨單元中。它們組合成節點,每個節點都是下列之一

  • 2-節點,就是說,它包含 1 個元素和 2 個兒子,
  • 3-節點,就是說,它包含 2 個元素和 3 個兒子,
  • 4-節點,就是說,它包含 3 個元素和 4 個兒子 。

每個兒子都是(可能為空)一個子 2-3-4 樹。節點是其中沒有父親的那個節點;它在遍歷樹的時候充當起點,因為從它可以到達所有的其他節點。葉子節點是有至少一個空兒子的節點。

B樹一樣,2-3-4 樹是有序的:每個元素必須大於或等於它左邊的和它的左子樹中的任何其他元素。每個兒子因此成為了由它的左和右元素界定的一個區間

2-3-4 樹是紅黑樹的一種等同,這意味著它們是等價的資料結構。換句話說,對於每個 2-3-4 樹,都存在著至少一個數據元素是相同次序的紅黑樹。在 2-3-4 樹上的插入和刪除操作也等價於在紅黑樹中的顏色翻轉和旋轉。這使得它成為理解紅黑樹背後的邏輯的重要工具。

字典樹

(又稱trie 樹,單詞查詢樹)

1.又稱單詞查詢樹,Trie樹,是一種樹形結構,是一種雜湊樹的變種。
典型應用是用於統計,排序和儲存大量的字串(但不僅限於字串),所以經常被搜尋引擎系統用於文字詞頻統計。

2.它的優點是:利用字串的公共字首來節約儲存空間,最大限度地減少無謂的字串比較,查詢效率比雜湊表高。

3.字典樹與字典很相似,當你要查一個單詞是不是在字典樹中,首先看單詞的第一個字母是不是在字典的第一層,如果不在,說明字典樹裡沒有該單詞,如果在就在該字母的孩子節點裡找是不是有單詞的第二個字母,沒有說明沒有該單詞,有的話用同樣的方法繼續查詢.字典樹不僅可以用來儲存字母,也可以儲存數字等其它資料。

用在統計和排序大量字串,如自動機。

trie 樹的一個典型應用是字首匹配,比如下面這個很常見的場景,在我們輸入時,搜尋引擎會給予提示

還有比如IP選路,也是字首匹配,一定程度會用到trie

  1. 字尾樹

  2. 廣義字尾樹


參考:

  1. https://www.cnblogs.com/zhuyf87/archive/2012/11/09/2763113.html 二叉排序樹
  2. https://www.cnblogs.com/fornever/archive/2011/11/15/2249492.html 平衡二叉樹(解惑)
  3. https://www.iteye.com/blog/hxraid-609949 平衡二叉查詢樹
  4. https://www.iteye.com/blog/hxraid-611816 紅黑樹(RBT)
  5. https://www.zhihu.com/question/30527705 樹的應用場景
  6. 說一下聚簇索引 & 非聚簇索引
  7. MySQL索引背後的資料結構及演算法原理