AVL树(二叉平衡树)详解与实现
生活随笔
收集整理的這篇文章主要介紹了
AVL树(二叉平衡树)详解与实现
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
公眾號文章鏈接
AVL樹概念
前面學(xué)習(xí)二叉查找樹和二叉樹的各種遍歷,但是其查找效率不穩(wěn)定(斜樹),而二叉平衡樹的用途更多。查找相比穩(wěn)定很多。(歡迎關(guān)注數(shù)據(jù)結(jié)構(gòu)專欄)
- AVL樹是帶有平衡條件的二叉查找樹。這個平衡條件必須要容易保持。而且要保證它的深度是O(logN).
- AVL的條件是左右樹的高度差(平衡因子)不大于1;并且它的每個子樹也都是平衡二叉樹。
- 對于平衡二叉樹的最小個數(shù),n0=0;n1=1;nk=n(k-1)+n(k-2)+1;(求法可以類比斐波那契!)
難點:AVL是一顆二叉排序樹,用什么樣的規(guī)則或者規(guī)律讓它能夠在復(fù)雜度不太高的情況下實現(xiàn)動態(tài)平衡呢?
不平衡概況
如果簡單的以單節(jié)點看,大致有上面四種情形,并且他們的最后結(jié)果也是有的有所相近。只是:上下會變動。該在左面的還在左面,改在右面的還在右面。 這只是針對在底部,對于可能出現(xiàn)的平衡要首先搞清楚: 所以針對四種不平衡,可能出現(xiàn)在底部,也可能出現(xiàn)在頭,也可能出現(xiàn)在某個中間節(jié)點導(dǎo)致不平衡。 而我們只需要研究其首次不平衡點,解決之后整棵樹即繼續(xù)平衡。當(dāng)然,在實際解決肯定會帶上遞歸的思想解決問題。四種平衡旋轉(zhuǎn)方式
RR平衡旋轉(zhuǎn)(左單旋轉(zhuǎn))
出現(xiàn)這種情況的原因是節(jié)點的右側(cè)的右側(cè)較深這時候不平衡節(jié)點需要左旋。再細看過程。- 再左旋的過程中,root(oldroot)節(jié)點下沉,中間節(jié)點(newroot)上浮.而其中中間節(jié)點(newroot)的右側(cè)依然不變。
- 它上浮左側(cè)所以需要指向根節(jié)點(oldroot)(畢竟一棵樹)。但是這樣newroot原來左側(cè)節(jié)點H空缺。而我們需要仍然讓整個樹完整并且滿足二叉排序樹的規(guī)則。
- 而剛好本來oldroot右側(cè)指向newroot變成oldroot被newroot左側(cè)指向。所以oldroot右側(cè)空缺,剛好這個位置滿足在oldroot的右側(cè)。在newroot的左側(cè)。.所以我們將H插入在這個位置。
- 其中H可能為NULL。不過不影響操作! 而左旋的代碼可以表示為:
LL平衡旋轉(zhuǎn)(右單旋轉(zhuǎn))
而右旋和左旋相反,但是思路相同,根據(jù)上述進行替換即可!
代碼: private node getLLbanlance(node oldroot) {//LL小,需要右旋轉(zhuǎn)// TODO Auto-generated method stubnode newroot=oldroot.left;oldroot.left=newroot.right;newroot.right=oldroot;oldroot.height=Math.max(getHeight(oldroot.left),getHeight(oldroot.right))+1;newroot.height=Math.max(getHeight(newroot.left),getHeight(newroot.right))+1;//原來的root的高度需要從新金酸 return newroot; } 復(fù)制代碼RL平衡旋轉(zhuǎn)(先右后左雙旋轉(zhuǎn))
產(chǎn)生不平衡的條件原因是:
- root節(jié)點右側(cè)左側(cè)節(jié)點的深度高些,使得與左側(cè)的差大于1.這個與我們前面看到的左旋右旋不同的是因為它的結(jié)構(gòu)不能直接變一下就可以完成。
- 因為對于右左結(jié)構(gòu),中間的最大,兩側(cè)的最小。但是下面的比上面大(下面在上面右側(cè))所以如果平衡的話,那么右左的R.L應(yīng)該在中間,而R應(yīng)該在右側(cè)。原來的root在左側(cè)。
- 所以節(jié)點的變化浮動比較大,而且需要妥善處理各個子節(jié)點的移動使其滿足二叉排序樹的性質(zhì)!
- 期間考慮樹高度變化即可!
這種雙旋轉(zhuǎn)其實也很簡單。不要被外表唬住?;谇懊娴膯涡D(zhuǎn),雙旋轉(zhuǎn)有兩種具體邏輯思路。 思路1:兩次旋轉(zhuǎn)RR,LL
根據(jù)上圖所圈的,先對底部使得底部的大小關(guān)系變化,使其在滿足二叉平衡樹的條件下還滿足RR結(jié)構(gòu)的二叉樹。所以只需要對右節(jié)點R先進行右旋,再對ROOT進行左旋即可。 思路2:直接分析 根據(jù)初始和結(jié)果的狀態(tài),然后分析各個節(jié)點變化順序。手動操作這些節(jié)點即可!- 首先根據(jù)ROOT,R,R.L三個節(jié)點變化。R.L肯定要在最頂層。左右分別指向ROOT和R。那么這其中R.left,ROOT.right發(fā)生變化(原來分別是R,L和R)暫時為空。而剛好根據(jù)左右大小關(guān)系可以補上R.L的左右節(jié)點。
- 這樣思考整棵樹也可以完成平衡,但是要考慮樹的高度變化。 代碼為:(注釋部分為方案1)
LR平衡旋轉(zhuǎn)(先左后右單旋轉(zhuǎn))
根據(jù)上述RL修改即可
private node getLRbanlance(node oldroot) {oldroot.left =getRRbanlance(oldroot.left);oldroot.height=Math.max(getHeight(oldroot.left), getHeight(oldroot.right))+1;return getLLbanlance(oldroot);} 復(fù)制代碼java代碼實現(xiàn)
- 首先對于節(jié)點多個height屬性。用于計算高度(平衡因子)
- 插入是遞歸插入。遞歸一個來回的過程,去的過程進行插入。**回的過程進行高度更新。和檢查是否平衡。**不要寫全局遞歸計算高度,效率太低下。事實上高度變化只和插入和平衡有關(guān),仔細考慮即不會有疏漏!
總結(jié)
測試情況:
- AVL的理解需要時間,當(dāng)然筆者的AVL自己寫的可能有些疏漏,如果有問題還請各位一起探討!
- 當(dāng)然,除了插入,AVL還有刪除等其他操作,(原理相似。刪除后平衡)有興趣可以一起研究。
- 如果需要源碼還請關(guān)注筆者公眾號:公眾號查看相關(guān)專題文章!
- 如果對后端、爬蟲、數(shù)據(jù)結(jié)構(gòu)算法等感性趣歡迎關(guān)注我的個人公眾號交流:bigsai(回復(fù)數(shù)據(jù)結(jié)構(gòu)、爬蟲、java等有精心準備資料一份!)
轉(zhuǎn)載于:https://juejin.im/post/5d62064c6fb9a06b2c329a6f
總結(jié)
以上是生活随笔為你收集整理的AVL树(二叉平衡树)详解与实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java Web学习(五)session
- 下一篇: 爬虫百度图片