看圖輕鬆理解數據結構與算法系列(AVL樹)

前言

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

AVL樹

AVL樹,也稱平衡二叉搜索樹,AVL是其發明者姓名簡寫。AVL樹屬於樹的一種,並且它也是一棵二叉搜索樹,不一樣的是他經過必定機制能保證二叉搜索樹的平衡,平衡的二叉搜索樹的查詢效率更高。算法

AVL樹特色

  • AVL樹是一棵二叉搜索樹。
  • AVL樹的左右子節點也是AVL樹。
  • AVL樹擁有二叉搜索樹的全部基本特色。
  • 每一個節點的左右子節點的高度之差的絕對值最多爲1,即平衡因子爲範圍爲[-1,1]。

image

圖中紅色數字表示對應節點的高度,能夠看到同一層的節點高度差都沒有超過1。sql

二叉搜索樹的平衡

基礎的二叉搜索樹構建出來可能會存在不平衡的現象,好比極端狀況下,按照A B C D E F G H順序插入樹中,結果爲,網絡

image

但實際上咱們更想要平衡一點的二叉搜索樹,由於平衡的二叉搜索樹能有效提升查詢效率,好比上面的要查詢「H」節點則須要比較8個節點才找到,而平衡的二叉搜索樹只須要比較3個節點。數據結構

因此AVL樹的出現就是爲了解決平衡性問題,它的核心內容就是平衡處理機制,即所謂的旋轉,一共有四種形式的旋轉:右單旋、左單旋、左右雙旋和右左雙旋。併發

爲何要旋轉

不論是什麼方式的旋轉,旋轉的目的是爲了下降樹的高度,使其平衡,假如樹結構以下圖,機器學習

image

將「A」節點添加到樹中,變成以下結構,樹產生了不平衡,因而檢查哪裏不平衡,當到「C」節點時發現高度差超過1,數據結構和算法

image

因此須要對「C」節點進行右單旋操做將高度降到2,達到平衡。學習

image

插入方式

AVL樹一共有四種插入方式,根據插入方式不一樣須要作不一樣的旋轉操做,如今往下看四種插入方式,設受插入節點影響而失去平衡的節點的父節點爲Z,.net

  • LL插入方式,插入的節點在Z節點的左子樹的左子樹上,以下圖,「A」節點插入影響「C」節點的平衡,「C」的父節點爲「E」,插入節點「A」在「E」節點的左子樹的左子樹上。即「B」節點的左右子節點都算LL插入。

image

  • RR插入方式,插入的節點在Z節點的右子樹的右子樹上,以下圖,「I」節點插入影響「G」節點的平衡,「G」的父節點爲「E」,插入節點「I」在「E」節點的右子樹的右子樹上。即「H」節點的左右子節點都算RR插入。

image

  • LR插入方式,插入的節點在Z節點的左子樹的右子樹上,以下圖,「C」節點插入影響「B」節點的平衡,「B」的父節點爲「E」,插入節點「C」在「E」節點的左子樹的右子樹上。即「D」節點的左右子節點都算LR插入。

image

  • RL插入方式,插入的節點在Z節點的右子樹的左子樹上,以下圖,「G」節點插入影響「H」節點的平衡,「H」的父節點爲「E」,插入節點「G」在「E」節點的右子樹的左子樹上。即「F」節點的左右子節點都算RL插入。

image

右單旋

右單旋用於處理LL插入方式,假設存在一棵樹,以下,

image

現插入「A」節點,假如不進行旋轉的話,樹結構爲下圖,因此遍歷過程也會檢查哪裏不平衡,檢查到「C」節點和「G」節點的高度差大於1,並且插入節點「A」屬於「E」節點左子樹的左子樹,因而進行右單旋,

image

「C」節點右單旋即將「C」節點提升,本來它的父節點「E」則變爲其右子節點,「C」節點原來的右子節點則變爲其父節點「E」的左子節點。右單旋後的結果以下,從新達到了平衡。

image

左單旋

左單旋用於處理RR插入方式,假設存在一棵樹,以下,

image

現插入「I」節點,假如不進行旋轉的話,樹結構爲下圖,因此遍歷過程也會檢查哪裏不平衡,檢查到「C」節點和「G」節點的高度差大於1,並且插入節點「I」屬於「E」節點的右子樹的右子樹,因而進行左單旋,

image

「G」節點左單旋即將「G」節點提升,本來它的父節點「E」則變爲其左子節點,「G」節點原來的左子節點則變爲其父節點「E」的右子節點。左單旋後的結果以下,從新達到了平衡。

image

左右雙旋

左右雙旋用於處理LR插入方式,假設存在一棵樹,以下,

image

現插入「C」節點,假如不進行旋轉的話,樹結構爲下圖,遍歷過程會檢查哪裏不平衡,檢查到「B」節點和「G」節點的高度差大於1,並且插入節點「C」屬於「E」節點的左子樹的右子樹,因而進行左右雙旋,

image

先以「D」節點爲軸進行左單旋,結果爲,

image

再以「D」節點爲軸進行右單旋,獲得最終結果,

image

右左雙旋

右左雙旋用於處理RL插入方式,假設存在一棵樹,以下,

image

現插入「G」節點,假如不進行旋轉的話,樹結構爲下圖,遍歷過程會檢查哪裏不平衡,檢查到「C」節點和「H」節點的高度差大於1,並且插入節點「G」屬於「E」節點的右子樹的左子樹,因而進行右左雙旋,

image

先以「F」節點爲軸進行右單旋,結果爲,

image

再以「F」節點爲軸進行左單旋,獲得最終結果,

image

插入

空樹時插入節點「E」直接做爲根節點,「E」節點高度設爲1,

image

繼續插入「B」節點,小於「E」節點則添加到左邊,且「E」節點高度加1,

image

繼續插入「G」節點,大於「E」節點則添加到右邊,此時「E」節點高度不變,

image

繼續插入「D」節點,最終到「B」節點的右子節點,此時「B」節點高度加1,「E」節點高度也加1,

image

繼續插入「C」節點,最終到「D」節點的左子節點,此時「D」、「B」、「E」節點高度都分別加1,而且先發現節點「D」與它同級節點(不存在即高度爲0)高度差大於1,而且屬於RL插入方式,使用右左雙旋處理,

image

以「C」節點爲軸進行右單旋,結果爲,

image

再以「C」節點爲軸進行左單旋,結果以下,能夠看到進過右左雙旋操做後二叉樹已經達到平衡了。

image

總結,插入時可能會遇到四種不一樣的插入方式,分別是:LL插入方式、RR插入方式、LR和RL插入方式。根據不一樣的插入方式對應作旋轉操做即能使樹達到平衡狀態。

查找

AVL樹由於屬於二叉搜索樹,因此查找時與BST樹徹底同樣,好比下面這棵樹,查找「D」節點,

image

從根節點「C」開始,

image

「D」大於「C」,因此往右繼續查找,

image

「D」小於「E」,因此往左查找,找到。

image

刪除

刪除操做主要分兩種狀況,一種是刪除後不會影響平衡,那麼直接按照BST樹規則刪除。另一種是刪除後會影響樹的平衡,那麼則須要再作旋轉處理。

狀況一

如樹的結構,要刪除「B」節點,

image

直接找到「B」節點,且由於是葉子節點,直接刪掉便可。

image

最終爲,

image

但若是刪除的不是「B」節點,而是「C」節點,則不能直接刪除「C」節點,

image

應該先找到「C」節點的前驅,它的前驅爲「B」節點,使用「B」替換「C」節點,

image

最後將原來的「B」節點刪除。

image

狀況二

如樹的結構,要刪除「F」節點,

image

先找到「F」節點,

image

而後將「F」節點刪除,此時致使了「C」節點和「G」節點的高度差超過1,須要作旋轉操做,

image

並且由於C節點的左子節點高度比右子節點高度大,因此執行右單旋操做,旋轉後爲,

image

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

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

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

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

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

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

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

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

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


跟我交流,向我提問:

歡迎關注:

相關文章
相關標籤/搜索