看圖輕鬆理解數據結構與算法系列(二叉搜索樹)

前言

推出一個新系列,《看圖輕鬆理解數據結構和算法》,主要使用圖片來描述常見的數據結構和算法,輕鬆閱讀並理解掌握。本系列包括各類堆、各類隊列、各類列表、各類樹、各類圖、各類排序等等幾十篇的樣子。mysql

關於樹

對於樹的數據結構你們都瞭解,只是樹的類型有不少,因此可能又會對樹產生一種陌生感。樹其實就是由有限n(n>=1)個節點組成的一個具備層次關係的集合,它看起來像一棵倒掛的樹,因此稱之爲「樹」。算法

樹的特色

  • 每一個節點有若干個或0個子節點;
  • 根節點沒有父節點;
  • 每個非根節點有且只有一個父節點;
  • 每一個子節點能夠分爲多個不相交的子樹;

二叉搜索樹

二叉搜索樹(Binary Search Tree,簡寫BST),又稱爲二叉排序樹,屬於樹的一種,經過二叉樹將數據組織起來,樹的每一個節點都包含了健值 key、數據值 data、左子節點指針、右子節點指針。其中健值 key 是最核心的部分,它的值決定了樹的組織形狀;數據值 data 是該節點對應的數據,有些場景能夠忽略,舉個例子,key 爲身份證號而 data 爲人名,經過身份證號找人名;左子節點指針指向左子節點;右子節點指針指向右子節點。sql

二叉搜索樹特色

  • 左右子樹也分別是二叉搜索樹。
  • 左子樹的全部節點 key 值都小於它的根節點的 key 值。
  • 右子樹的全部節點 key 值都大於他的根節點的 key 值。
  • 二叉搜索樹能夠爲一棵空樹。
  • 通常來講,樹中的每一個節點的 key 值都不相等,但根據須要也能夠將相同的 key 值插入樹中。

image

插入操做

  1. 若是爲空樹則將插入節點做爲根節點。
  2. 若是不爲空樹則從根節點開始,比較插入節點與根節點的 key 值,值相同則不作任何處理直接返回,大於則繼續比較右子節點R,小於則繼續比較左子節點L。
  3. 右子節點R與插入節點比較,插入節點的 key 值大的話則繼續往R節點的右子節點比較,小於的話則繼續往R節點左子節點比較。
  4. 以此類推不斷往下尋找,直到找到左子節點指針或右子節點指針爲空的節點,將插入節點放進去。

對於下面這棵樹,插入DH網絡

image

建立D節點並與根節點比較,數據結構

image

D 小於 E,因而往左子節點繼續比較,併發

image

D 大於 C,應該往右子節點方向,而此時 C 節點的右子節點指針爲空,D 節點能夠放置進去。機器學習

image

一樣的,對於 H 節點,先建立 H 節點並與根節點比較,數據結構和算法

image

H 大於 E,因而往右子節點繼續比較,學習

image

H 大於 G,應該往右子節點方向,而此時 G 節點的右子節點指針爲空,H 節點能夠放置進去。.net

image

插入順序性

二叉搜索樹的形狀與節點插入順序不一樣而可能不一樣,好比對於A B C D E F G H這些節點集,按E C A B D G F H順序插入則爲,

image

而若是調換前面兩個節點,按照C E A B D G F H順序插入則以下圖,形狀差異仍是挺大的,

image

極端狀況下,按照A B C D E F G H順序插入,則爲,

image

查詢操做

  1. 則從根節點開始,比較查詢節點與根節點的 key 值,值相同則表示找到該節點,直接返回,大於則繼續往右子節點R查找,小於則繼續往左子節點L查找。
  2. 右子節點R與查詢節點比較,查詢節點的 key 值大的話則繼續往R節點的右子節點查找,小於的話則繼續往R節點左子節點查找。
  3. 以此類推不斷往下尋找,直到找到節點的 key 值與查詢節點的相同,則表示查找成功,若是最終找不到則說明不存在該節點。

對於下圖的樹查找 key 值爲「B」和「G」的節點,

image

「B」與根節點的 key 值比較,

image

「B」小於「E」,往左子節點繼續尋找,

image

「B」小於「C」,往左子節點繼續尋找,

image

「B」大於「A」,往右子節點繼續尋找,二者相等,找到。

image

繼續查詢 key 值爲「G」的節點,與根節點比較,

image

「G」大於「E」,往右子節點,二者相等,找到。

image

刪除操做

刪除操做分三種狀況進行,

  • 若是刪除的節點爲葉子節點,即它的左子節點指針和右子節點指針都爲空時,則能夠直接刪掉該節點,並不會影響整棵樹的結構。
  • 若是刪除的節點只有一個子節點(左子節點或右子節點),則直接將子節點提高到被刪除的節點位置。
  • 若是刪除的節點有兩個子節點,此時須要找到刪除節點的中序後繼或中序前驅來填補刪除節點,中序後繼其實就是全部大於刪除節點中最小的那個,而中序前驅就是全部小於刪除節點中最大的那個,由於二叉搜索樹通過中序遍歷後是一個遞增序列,因此後繼就是刪除節點的後面那個節點,大於且大得最少的那個,好比1 2 3 4 5中4就是3的後繼。前驅就是刪除節點前面那個節點,好比1 2 3 4 5中2就是3的前驅。

狀況一

刪除「B」葉子結點,從根節點開始查找,

image

image

image

image

找到,直接刪除,

image

狀況二

假如樹的結構以下圖,如今要刪除「C」節點,

image

從根節點開始找,

image

image

找到「C」節點,直接將原來指向「C」節點的右子節點指針指向「C」的子節點,

image

最終爲,

image

狀況三

要在以下的樹中刪除「E」節點,

image

「E」節點存在兩個子節點,因而開始尋找「E」節點的中序前驅來替換它,前驅在左子節點「C」下最大值的那個節點,

image

要找「C」節點下最大值節點則一直往右,

image

直到不能繼續往下,即「D」節點便是前驅,用「D」節點來替換「E」節點,

image

最終實現將「E」節點刪除。

image

-------------推薦閱讀------------

個人開源項目彙總(機器&深度學習、NLP、網絡IO、AIML、mysql協議、chatbot)

爲何寫《Tomcat內核設計剖析》

個人2017文章彙總——機器學習篇

個人2017文章彙總——Java及中間件

個人2017文章彙總——深度學習篇

個人2017文章彙總——JDK源碼篇

個人2017文章彙總——天然語言處理篇

個人2017文章彙總——Java併發篇


跟我交流,向我提問:

歡迎關注:

相關文章
相關標籤/搜索