《程序設計與數據結構》第七週學習總結

學號 20172326 《程序設計與數據結構》第七週學習總結

教材學習內容總結

AVL樹

  • AVL樹是實現平衡二叉樹的一種算法實現,別的方法也可實現例如紅黑樹。
  • 平衡因子:右子樹高度-左子樹高度的差值(高度是指當前結點到葉子結點的最長路徑,如全部葉子結點的高度都爲0,而深度則是指從根結點到當前結點的最大路徑,如根結點的深度爲0。),規定AVL樹的平衡因子不大於1。因此在一個已經實現的AVL樹中,任意一個節點的平衡因子的取值爲(1,-1,0)。
  • 左旋,右旋,左右旋,右左旋。當進行插入抑或是刪除操做時,可能致使一個平衡二叉樹失衡,所以就要對其進行調整,使其恢復平衡。能夠簡單的用列表遍歷這個數,從新構造一個新的樹,但這種方法太過簡單,粗暴。因此咱們可使用旋轉樹,來使其恢復平衡。如下是幾種失衡的AVL樹。
  • 右旋(或稱爲左左旋),通過計算,發現某一失衡點的左子樹的深度大於右子樹,這時就須要將左子樹向「右」旋轉,使其恢復平衡。方法:將失衡點的左結點設爲當前樹的新根,使原根變爲新根的右結點,將新根的右結點變爲原根的左結點。
  • 左旋,失衡點處右子樹的深度大於左子樹,將右子樹向左旋轉。原理與右旋對稱。
  • 當某一子樹太深時,僅經過一次右旋或左旋將沒法完成,所以,咱們須要使用兩次旋轉來實現它。由於旋轉方法老是對稱的,因此,只拿左右旋轉爲例。
  • 左右旋,當左孩子的右子樹太深時,進行旋轉。先將其父節點變爲其左孩子,同時將其左左孩子進行分配。
  • 在執行結束操做後,經過比較每一個結點的平衡因子來維持AVL樹的平衡html

    紅黑樹

  • 根結點爲黑色;每一個結點只有紅色或黑色;全部的葉結點爲黑色;紅結點的孩子均爲黑色;對於每一個結點,從該結點到其葉子結點構成的全部路徑上的黑結點個數相同;
  • 插入結點。1.插入結點爲對應的根結點,直接將其塗黑便可。2.插入結點的父節點爲黑結點,那麼,直接插入便可。3.插入的父節點爲紅色。此時將破壞紅黑樹的結構,所以須要將其進行旋轉。 分爲如下三種狀況,知足之一的條件時,進行遞歸。
    • 當插入結點的父結點爲紅,且叔結點也爲紅時,將其父結點與叔結點改成紅色,祖父結點變爲黑色。並將帶操做結點改成祖父結點
    • 當待操做結點的父節點是紅色的,叔叔節點是黑色的,且插入節點是其父節點的右子節點。這時,將待操做結點改成其父結點,再將帶操做結點左旋。
    • 待操做結點的父結點是紅色,叔叔結點是黑色,且插入結點是其父結點的左子結點。咱們要作的操做有:將當前結點的父結點塗黑,將祖父結點塗紅,在祖父結點爲支點作右旋操做。最後把根結點塗黑,整個紅-黑樹從新恢復了平衡。
  • 刪除操做:
    • 第一步:將紅黑樹看成一顆二叉查找樹,將節點刪除。
      這和"刪除常規二叉查找樹中刪除節點的方法是同樣的"。分3種狀況:
      ① 被刪除節點沒有兒子,即爲葉節點。那麼,直接將該節點刪除就OK了。
      ② 被刪除節點只有一個兒子。那麼,直接刪除該節點,並用該節點的惟一子節點頂替它的位置。
      ③ 被刪除節點有兩個兒子。那麼,先找出它的後繼節點;而後把「它的後繼節點的內容」複製給「該節點的內容」;以後,刪除「它的後繼節點」。在這裏,後繼節點至關於替身,在將後繼節點的內容複製給"被刪除節點"以後,再將後繼節點刪除。這樣就巧妙的將問題轉換爲"刪除後繼節點"的狀況了,下面就考慮後繼節點。 在"被刪除節點"有兩個非空子節點的狀況下,它的後繼節點不多是雙子非空。既然"的後繼節點"不可能雙子都非空,就意味着"該節點的後繼節點"要麼沒有兒子,要麼只有一個兒子。若沒有兒子,則按"狀況① "進行處理;若只有一個兒子,則按"狀況② "進行處理。
    • 第二步:經過"旋轉和從新着色"等一系列來修正該樹,使之從新成爲一棵紅黑樹。
      由於"第一步"中刪除節點以後,可能會違背紅黑樹的特性。因此須要經過"旋轉和從新着色"來修正該樹,使之從新成爲一棵紅黑樹。

教材學習中的問題和解決過程

  • 問題1:
Comparable<T> comparableElement = (Comparable<T>)element

爲何要使用comparable來將element轉爲相關格式呢?java

  • 問題1理解:這是添加元素方法(addElement)的一部分代碼,將傳入的參數轉化爲comparable型。爲何不在傳入的時候直接將其變爲comparable類型呢?何況直接變爲comparable型數據,在以後的維護平衡樹時有助於進行插入元素之間的比較。咱們知道,在方法中傳入一個comparable參數看似簡單,但在真正經過輸入數據的時候,多是一個string值,也多是一個int值,可是,想傳入一個comparable類型數據,基本不可能,因此,選擇了在方法中進行類型轉化。
  • 問題2:紅黑樹的平衡問題
  • 問題2理解:首先,咱們知道,紅黑樹經過顏色來控制平衡。尤爲是黑色結點,經過每條路徑有相同數目的黑色結點。同時,每一個紅色結點的孩子結點爲黑色。能夠想象,想沿着一邊子樹的一個方向插入衆多的結點將不可實現,從而實現了平衡。同時,根據二叉查找樹的性質可知,若刪除一個結點,除非該結點爲根結點且爲紅色,不然必需通過一些操做以維持平衡。
  • 在課堂上,你們發現了一個問題。這種時候,應該怎樣操做,對於結點(7)結點(8),不管將其變爲黑色仍是紅色,都符合要求。那麼,爲何還要將其塗爲紅色呢?
  • 塗爲紅色,有什麼變化呢?相較於塗爲黑色,黑色結點減小,且其孩子結點爲黑色。若是是黑色呢?該樹總體黑色結點增多。但問題偏偏就在這裏,若是這是一顆單獨的樹還好說,但若是是某一棵樹的子樹呢?只有這一部分的黑色結點增長,別的均不變,這直接致使違反了規定。因此,從中也能夠看出,對於紅黑樹,黑色結點的變化是至關慎重的。從規定插入的結點默認爲紅色也能夠看出這點。git

    代碼問題

  • 問題1:AVL樹實現動態平衡的方法
  • 理解:當順序輸入一組數據「1 2 3 4 5 6 7 8 9」時,若是沒有相應的平衡方法,就會出現這種狀況。
  • 這種狀況以前博客也曾提到,是平衡二叉樹決不能出現的狀況,那麼,應該如何處理呢?從思路分析,咱們必需要更換根結點的元素,也就是說當一組數據順序進入時,一旦違反平衡因子的大小,馬上對樹中的元素進行對比,將可以平衡樹的根找出來,相似於將以前的樹折成兩半。理想的效果是這樣的,也就是說,平衡是動態的,隨時根據平衡因子的大小來調整樹的元素分佈。

所以,一開始,個人思路是,經過比較全部元素來肯定一箇中間大小的數據來做爲根。但是,這一實現過程較爲麻煩,須要將當前樹進行重構。翻了翻書,看到大篇幅的旋轉,我就知道應該怎樣作了。能夠看到,每次旋轉,都是由部分到總體,從某一棵失衡的子樹開始,再向上旋轉,再判斷再旋轉。因此,這是一個重複的過程,所以,能夠用遞歸實現。代碼將較爲簡單。算法

if (data.compareTo(p.getElement()) < 0) {//向左子樹尋找插入位置
            p.setLeft(insert(data, p.getLeft())); 
 if (height(p.getLeft()) - height(p.getRight()) == 2) {//插入後計算子樹的高度,等於2則須要從新恢復平衡,因爲是左邊插入,左子樹的高度確定大於等於右子樹的高度

                //判斷data是插入點的左孩子仍是右孩子
                if (data.compareTo(p.getLeft().getElement()) < 0) {
                    //進行LL旋轉
                    p = singleRotateLeft(p);
                } else {
                    //進行左右旋轉
                    p = doubleRotateWithLeft(p);
                }
            }
        }

這裏是部分代碼,所有的有點長,就不進行展現。這裏最爲關鍵的就是這行代碼「 p.setLeft(insert(data, p.getLeft()));
」也就是重複利用遞歸的部分,經過代替循環體,咱們直接鎖定須要插入的位置,在插入結束後,直接就插入結點的父結點的平衡因子來判斷插入是否致使失衡,也就是與2進行判斷,若是違規,直接進行旋轉。這樣一來,在樹的底層位置進行旋轉,儘量縮小涉及到的範圍,也就使得更加便於實現。segmentfault

代碼託管

其餘(感悟、思考等,可選)

  • 本章的知識很差理解,尤爲是紅黑樹,涉及了大量的不一樣狀況,使人頭禿,並且網上的知識有漏洞的也不少,繼續本身體會。數據結構

    學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 0/0 1/1 3/3
第二週 409/409 1/2 5/8
第三週 1174/1583 1/3 10/18
第四周 1843/3426 2/5 10/28
第五週 539/3965 2/7 20/48
第六週 965/4936 1/8 20/68
第七週 766/5702 1/9 20/88

結對及互評

  • 博客中值得學習的或問題:
    排版精美,對於問題研究得很細緻,解答也很周全。
  • 代碼中值得學習的或問題:
    代碼寫的很規範,思路很清晰,繼續加油!

點評過的同窗博客和代碼

  • 本週結對學習狀況
  • 20172313
  • 20172332學習

    結對學習內容

  • 第十一章 二叉查找樹.net

參考資料

相關文章
相關標籤/搜索