推出一個新系列,《看圖輕鬆理解數據結構和算法》,主要使用圖片來描述常見的數據結構和算法,輕鬆閱讀並理解掌握。本系列包括各類堆、各類隊列、各類列表、各類樹、各類圖、各類排序等等幾十篇的樣子。mysql
AVL樹,也稱平衡二叉搜索樹,AVL是其發明者姓名簡寫。AVL樹屬於樹的一種,並且它也是一棵二叉搜索樹,不一樣的是他經過必定機制能保證二叉搜索樹的平衡,平衡的二叉搜索樹的查詢效率更高。算法
圖中紅色數字表示對應節點的高度,能夠看到同一層的節點高度差都沒有超過1。sql
基礎的二叉搜索樹構建出來可能會存在不平衡的現象,好比極端狀況下,按照A B C D E F G H
順序插入樹中,結果爲,網絡
但實際上咱們更想要平衡一點的二叉搜索樹,由於平衡的二叉搜索樹能有效提升查詢效率,好比上面的要查詢「H」節點則須要比較8個節點才找到,而平衡的二叉搜索樹只須要比較3個節點。數據結構
因此AVL樹的出現就是爲了解決平衡性問題,它的核心內容就是平衡處理機制,即所謂的旋轉,一共有四種形式的旋轉:右單旋、左單旋、左右雙旋和右左雙旋。併發
不論是什麼方式的旋轉,旋轉的目的是爲了下降樹的高度,使其平衡,假如樹結構以下圖,機器學習
將「A」節點添加到樹中,變成以下結構,樹產生了不平衡,因而檢查哪裏不平衡,當到「C」節點時發現高度差超過1,數據結構和算法
因此須要對「C」節點進行右單旋操做將高度降到2,達到平衡。學習
AVL樹一共有四種插入方式,根據插入方式不一樣須要作不一樣的旋轉操做,如今往下看四種插入方式,設受插入節點影響而失去平衡的節點的父節點爲Z,.net
右單旋用於處理LL插入方式,假設存在一棵樹,以下,
現插入「A」節點,假如不進行旋轉的話,樹結構爲下圖,因此遍歷過程也會檢查哪裏不平衡,檢查到「C」節點和「G」節點的高度差大於1,並且插入節點「A」屬於「E」節點左子樹的左子樹,因而進行右單旋,
「C」節點右單旋即將「C」節點提升,本來它的父節點「E」則變爲其右子節點,「C」節點原來的右子節點則變爲其父節點「E」的左子節點。右單旋後的結果以下,從新達到了平衡。
左單旋用於處理RR插入方式,假設存在一棵樹,以下,
現插入「I」節點,假如不進行旋轉的話,樹結構爲下圖,因此遍歷過程也會檢查哪裏不平衡,檢查到「C」節點和「G」節點的高度差大於1,並且插入節點「I」屬於「E」節點的右子樹的右子樹,因而進行左單旋,
「G」節點左單旋即將「G」節點提升,本來它的父節點「E」則變爲其左子節點,「G」節點原來的左子節點則變爲其父節點「E」的右子節點。左單旋後的結果以下,從新達到了平衡。
左右雙旋用於處理LR插入方式,假設存在一棵樹,以下,
現插入「C」節點,假如不進行旋轉的話,樹結構爲下圖,遍歷過程會檢查哪裏不平衡,檢查到「B」節點和「G」節點的高度差大於1,並且插入節點「C」屬於「E」節點的左子樹的右子樹,因而進行左右雙旋,
先以「D」節點爲軸進行左單旋,結果爲,
再以「D」節點爲軸進行右單旋,獲得最終結果,
右左雙旋用於處理RL插入方式,假設存在一棵樹,以下,
現插入「G」節點,假如不進行旋轉的話,樹結構爲下圖,遍歷過程會檢查哪裏不平衡,檢查到「C」節點和「H」節點的高度差大於1,並且插入節點「G」屬於「E」節點的右子樹的左子樹,因而進行右左雙旋,
先以「F」節點爲軸進行右單旋,結果爲,
再以「F」節點爲軸進行左單旋,獲得最終結果,
空樹時插入節點「E」直接做爲根節點,「E」節點高度設爲1,
繼續插入「B」節點,小於「E」節點則添加到左邊,且「E」節點高度加1,
繼續插入「G」節點,大於「E」節點則添加到右邊,此時「E」節點高度不變,
繼續插入「D」節點,最終到「B」節點的右子節點,此時「B」節點高度加1,「E」節點高度也加1,
繼續插入「C」節點,最終到「D」節點的左子節點,此時「D」、「B」、「E」節點高度都分別加1,而且先發現節點「D」與它同級節點(不存在即高度爲0)高度差大於1,而且屬於RL插入方式,使用右左雙旋處理,
以「C」節點爲軸進行右單旋,結果爲,
再以「C」節點爲軸進行左單旋,結果以下,能夠看到進過右左雙旋操做後二叉樹已經達到平衡了。
總結,插入時可能會遇到四種不一樣的插入方式,分別是:LL插入方式、RR插入方式、LR和RL插入方式。根據不一樣的插入方式對應作旋轉操做即能使樹達到平衡狀態。
AVL樹由於屬於二叉搜索樹,因此查找時與BST樹徹底同樣,好比下面這棵樹,查找「D」節點,
從根節點「C」開始,
「D」大於「C」,因此往右繼續查找,
「D」小於「E」,因此往左查找,找到。
刪除操做主要分兩種狀況,一種是刪除後不會影響平衡,那麼直接按照BST樹規則刪除。另一種是刪除後會影響樹的平衡,那麼則須要再作旋轉處理。
如樹的結構,要刪除「B」節點,
直接找到「B」節點,且由於是葉子節點,直接刪掉便可。
最終爲,
但若是刪除的不是「B」節點,而是「C」節點,則不能直接刪除「C」節點,
應該先找到「C」節點的前驅,它的前驅爲「B」節點,使用「B」替換「C」節點,
最後將原來的「B」節點刪除。
如樹的結構,要刪除「F」節點,
先找到「F」節點,
而後將「F」節點刪除,此時致使了「C」節點和「G」節點的高度差超過1,須要作旋轉操做,
並且由於C節點的左子節點高度比右子節點高度大,因此執行右單旋操做,旋轉後爲,
-------------推薦閱讀------------
個人開源項目彙總(機器&深度學習、NLP、網絡IO、AIML、mysql協議、chatbot)
跟我交流,向我提問:
歡迎關注: