數據結構中的樹(二叉樹、二叉搜索樹、AVL樹)

數據結構動圖展現網站html

樹的概念

樹(英語:tree)是一種抽象數據類型(ADT)或是實做這種抽象數據類型的數據結構,用來模擬具備樹狀結構性質的數據集合。它是由n(n>=1)個有限節點組成一個具備層次關係的集合。把它叫作「樹」是由於它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具備如下的特色:mysql

  • 每一個節點有零個或多個子節點;git

  • 沒有父節點的節點稱爲根節點;github

  • 每個非根節點有且只有一個父節點;算法

  • 除了根節點外,每一個子節點能夠分爲多個不相交的子樹;sql

  • 節點的度:一個節點含有的子樹的個數稱爲該節點的度;數據庫

  • 樹的度:一棵樹中,最大的節點的度稱爲樹的度;數據結構

  • 葉節點或終端節點:度爲零的節點;框架

  • 父親節點或父節點:若一個節點含有子節點,則這個節點稱爲其子節點的父節點;機器學習

  • 孩子節點或子節點:一個節點含有的子樹的根節點稱爲該節點的子節點;

  • 兄弟節點:具備相同父節點的節點互稱爲兄弟節點;

  • 節點的層次:從根開始定義起,根爲第1層,根的子節點爲第2層,以此類推;

  • 樹的高度或深度:樹中節點的最大層次;

  • 堂兄弟節點:父節點在同一層的節點互爲堂兄弟;

  • 節點的祖先:從根到該節點所經分支上的全部節點;

  • 子孫:以某節點爲根的子樹中任一節點都稱爲該節點的子孫。

  • 森林:由m(m>=0)棵互不相交的樹的集合稱爲森林;

二叉樹

每一個節點最多含有兩個子樹的樹稱爲二叉樹

  • 平衡二叉樹(AVG樹): 當且僅當任何節點的兩棵子樹的高度差不大於1的二叉樹
  • 徹底二叉樹: 對於一顆二叉樹,假設其深度爲d(d>1)。除了第d層外,其它各層的節點數目均已達最大值,且第d層全部節點從左向右連續地緊密排列,這樣的二叉樹被稱爲徹底二叉樹,其中滿二叉樹的定義是全部葉節點都在最底層的徹底二叉樹;
  • 排序二叉樹: (二叉查找數 Binary Search Tree), 也稱二叉搜索樹,有序二叉樹,任意一個結點左邊子節點的數據要比根結點的值小,右邊子節點的數據要比根結點的值大。可是若是二叉樹是單增的狀況會退化成鏈表

二叉樹的遍歷

  1. 深度優先遍歷
  • 先序遍歷 preorder 在先序遍歷中,咱們先訪問根節點,而後遞歸使用先序遍歷訪問左子樹,再遞歸使用先序遍歷訪問右子樹 根節點->左子樹->右子樹
  • 中序遍歷 inorder 在中序遍歷中,咱們遞歸使用中序遍歷訪問左子樹,而後訪問根節點,最後再遞歸使用中序遍歷訪問右子樹 左子樹->根節點->右子樹
  • 後序遍歷 postorder 在後序遍歷中,咱們先遞歸使用後序遍歷訪問左子樹和右子樹,最後訪問根節點 左子樹->右子樹->根節點
    image.png)
  1. 廣度優先遍歷(層次遍歷)

二叉樹反推

若是已知中序和先序,或者中序和後序,能夠肯定二叉樹的結構

eg:
先序:A B C D E F
中序: C B A E D F

先序找根,中序定兩邊
先序遍歷序列爲ABCDEF,第一個字母是A被打印出來,就說明A是根結點的數據。
再由中序遍歷序列是CBAEDF,能夠知道C和B是A的左子樹的結點,
E、D、F是A的右子樹的結點

image.png

而後咱們看先序中的C和B,它的順序是ABCDEF,B是在C的前面打印,因此B應該是A的左孩子,而C就只能是B的孩子,此時是左仍是右孩子還不肯定。再看中序序列是CBAEDF,C是在B的前面打印,這就說明C是B的左孩子,不然就是右孩子了

image.png

再看先序中的E、D、F,它的順序是ABCDEF,那就意味着D是A結點的右孩子,E和F是D的子孫,注意,它們中有一個不必定是孩子,還有多是孫子的。再來看中序序列是CBAEDF,因爲E在D的左側,而F在右側,因此能夠肯定E是D的左孩子,F是D的右孩子

image.png

注:若是已經先序和後序沒法判斷二叉樹結構

先序序列:ABC

後序序列:CBA

咱們能夠肯定A必定是根結點,但接下來,咱們沒法知道,哪一個結點是左子樹,哪一個是右子樹

image.png

二叉查找樹(二叉搜索樹)

節點的左子樹只包含小於當前節點的數。

節點的右子樹只包含大於當前節點的數。

全部左子樹和右子樹自身必須也是二叉搜索樹

Python實現二叉查找樹

參考如下兩篇文章(最好是本身畫圖容易理解):

二叉平衡樹

Python實現平衡二叉樹 刪除和添加調整的是最小不平衡子樹

平衡二叉樹 (Height-Balanced Binary Search Tree) 是一種二叉排序樹,

其中每個結點的左子樹和右子樹的高度差不超過1(小於等於1)

二叉樹的平衡因子 (Balance Factor) 等於該結點的左子樹深度減去右子樹深度的值稱爲平衡因子。平衡因子只多是[-1,0,1]。距離插入結點最近的,且平衡因子的絕對值大於1的結點爲根的子樹,稱爲最小不平衡子樹

平衡二叉樹就是二叉樹的構建過程當中,每當插入一個結點,看是否是由於樹的插入破壞了樹的平衡性,如果,則找出最小不平衡樹。在保持二叉樹特性的前提下,調整最小不平衡子樹中各個結點之間的連接關係,進行相應的旋轉,使之成爲新的平衡子樹。簡記爲: 步步調整,步步平衡

參考如下兩篇文章(最好是本身畫圖):

注:第一篇文章中針對左右失衡和右左失衡的處理圖片和代碼中有誤,可是主要是看我的理解,做者能夠只對根節點進行失衡處理,而我這邊是按照第二篇文章說的,調整最小不平衡子樹

對於其中添加元素的遞歸代碼的理解:

霍夫曼樹

(用於信息編碼):帶權路徑最短的二叉樹稱爲哈夫曼樹或最優二叉樹;
應用: 壓縮文件

B樹(B-Tree)

一種對讀寫操做進行優化的自平衡的二叉查找樹,可以保持數據有序,擁有多餘兩個子樹。B樹是多路平衡查找樹,2階B樹纔是平衡二叉樹
應用: 數據庫存儲

M階的Btree的幾個重要特性:

  1. 節點最多含有m棵字樹(指針), m-1個關鍵字(存的數據,空間)(m > 2)
  2. 除根節點和葉子節點外,其餘每一個節點至少有ceil(m / 2)個子節點,(ceil爲上取整)
  3. 若根節點不是葉子節點,則至少有兩棵子樹

M階: 這個由磁盤的頁大小決定,頁內存是4KB, 好處是一次性取數據就能夠取出這個節點即這個頁數據,不會形成IO讀取的浪費。

img

B+Tree

  1. 每一個節點最多有m個子節點
  2. 除根節點外,每一個節點至少有m/2個子節點,注意若是結果除不盡,就取上蒸,如 5/2=3
  3. 根節點要麼是空,要麼是獨根,不然至少有2個子節點
  4. 有k個子節點的節點必有k個關鍵字
  5. 葉節點的高度一致

image.png

img

適合大數據的磁盤索引,經典的MySQL,全部的數據都存在葉子節點,其餘上層節點都是索引,增長了系統的穩定性以及遍歷查找效率。葉子節點之間是雙向指針,這一點就有利於範圍查找。

MyISAM存儲引擎的數據結構(非彙集)

索引文件和數據文件是分離的,非彙集(非聚族)

image.png

.MYD 存儲數據的文件

.MYI 存儲索引的文件

.FRM 表結構文件,管理索引和數據的框架

InnoDB索引的實現(彙集)

  • 表數據自己就是按B+Tree組織的一個索引結構文件
  • 彙集索引-葉子節點包含了完整的數據記錄,索引跟數據合併,MySQL默認節點大小爲16KB,因此說高度爲3的B+樹就可以存儲千萬級別的數據。
  • 爲何InnoDB表必須有主鍵,而且推薦使用整形的自增主鍵?
    • 整形存儲佔用比較少,且比較容易,若是是uuid字符串還須要進行轉換且佔用空間大
    • 使用自增是爲了不二叉樹的頻繁自平衡分裂,自增主鍵,只須要每次都忘後面增長便可,不會形成大範圍的性能開銷
  • 爲何非主鍵索引結構葉子節點存儲的是主鍵值?(一直性)

image.png

聯合索引的底層存儲結構

image.png

  1. B站-100分鐘講透MySQL索引底層原理

  2. MySQL底層索引算法

  3. 爲何 MySQL 使用 B+ 樹

  4. MYSQL-B+TREE索引原理-詳細解釋了SQL語句的執行過程

常見樹的應用場景

  1. xml,html等,那麼編寫這些東西的解析器的時候,不可避免用到樹
  2. 路由協議就是使用了樹的算法
  3. mysql數據庫索引
  4. 文件系統的目錄結構
  5. 因此不少經典的AI算法其實都是樹搜索,此外機器學習中的decision tree也是樹結構

image.png

相關文章
相關標籤/搜索