20172310 2017-2018《程序設計與數據結構》(下)第八週學習總結

20172310 2017-2018《程序設計與數據結構》(下)第八週學習總結

教材學習內容總結

1.一、堆

  • 堆(heap):是具備兩個附加屬性的二叉樹。一是堆是一顆徹底樹(若是一棵二叉樹是平衡的,即全部葉子都位於h或h-1層,其中h爲log2n, 且n是樹中的元素數目,且全部h層中的葉子都位於該樹的左邊,那麼該樹就被認爲是徹底的。),二是對每一結點,它小於或等於(大於或等於)其左孩子和右孩子。
  • 小於或等於其左孩子和右孩子的是最小堆(minheap),結點大於或等於它的左右孩子是最大堆(maxheap), 其中的結點大於或等於它的左右孩子。關鍵概念html

  • 最小堆將其最小元素存儲在該二叉樹的根處,且其根的兩個孩子一樣也是最小堆。
    java

  • 堆的接口:git


1.二、addElement操做

  • addElement方法將給定的Comparable元素添加到堆中的恰當位置處,且維持該堆的徹底性屬性和有序屬性。因此完成addElement方法有兩個步驟,一是將元素放入堆中,二是調整元素的位置,保持堆的性質。
    • 放入的位置:一個堆就是棵徹底樹, 因此對於插入的新結點而言只存在一個正確的位置, 且它要麼是h層左邊的下一個空位置,要麼是h+1層左邊的第1個位置(若是h層是滿的話)
    • 排序屬性:第一將該新元素和其父親的值進行比較,若是該新結點小於其雙親則將它們互換;而後重複,沿着樹向上,直至該新元素要麼是大於其雙親要麼是位於該堆的根處。在堆實現中,咱們會對樹中的最末個結點,進行跟蹤記錄。

1.三、 removeMin 操做

  • 最小元素是存儲在最小堆的根處的,因此要作的就是返回根元素並用堆中的另外一元素替換它。
    • 替換:與addElement操做同樣,是要維持該樹的徹底性,那麼只有一個能替換根的合法元素,那就是是存儲在樹中最末片葉子上的元素。
    • 重排:將該新根元素與其較小的孩子進行比較,且若是孩子更小則將它們互換。沿着樹向下繼續這過程,直到該元素要麼位於某葉子中, 要麼比它的兩個孩子都小。

1.四、findMin操做

  • 堆中最小元素元素老是被存儲在該樹的根處,因此實現findMin方法只需經過返回存儲在根處的元素。

2.一、使用堆: 優先級隊列

  • 優先級隊列(priority queue) 是遵循兩個排序規則的集合。
    • 具備更高優先級的項目在先。
    • 具備相同優先級的項目使用先進先出方法來肯定其排序。
  • 優先級隊列實現方式有兩種使用隊列列表或最小堆。雖然最小堆根本就不是一個隊列,可是它卻提供了一個高效的優先級隊列實現。
  • 過程:建立個PriorityQueueNode對象,用來存儲將被放置在隊列中的元素、該元素的優先級、以及元素放進隊列的順序。而後,使用compareTo 方法,對優先級進行比較,而後在優先級相同的時候再對階進行比較。

三、用鏈表實現堆

  • 由於咱們要求在插入元素後可以向上遍歷該樹,因此堆中結點必須存儲指向其雙親的指針。
  • 堆接口中定義的方法用鏈表實現,實現的算法和邏輯就是上述所寫的。
    • 鏈表實現中實例化一個HeapNode類的LastNode引用,來跟蹤記錄堆中的最末一片葉子。
    • addElement方法還調用了兩個私有方法來實現上述的兩個步驟,其操做的複雜度爲2×log n +1+log n ,即O(log n)。
    • addElement方法中調用的第二個重排序的方法實際上並無執行雙親與孩子的完整互換,它只是把雙親元素往下平移到正確的插入點,其複雜度也是O(log n)。可是,它的確提升了效率,由於它減小了在堆的每一層上要執行的賦值次數。
    • removeMin方法同理,時間複雜度爲2Xlogn+logn+1,即O(log n)。
    • findMin方法的時間複雜度爲O(1)。

四、用數組實現堆

  • 在二叉樹的數組實現中,樹的根位於位置0處,對於每一結點n, n的左孩子將位於數組的2n+1位置處,n的右孩子將位於數組的2(n+ 1)位置處,所以咱們可以計算
    雙親和孩子的位置。
  • 數組實現的addElement方法必須首先檢查可用空間,如須要,要對該數組進行擴容。
    • 與鏈表實現不一樣,數組實現不須要肯定新結點雙親的步驟。
    • 數組實現的addElement操做的時間複雜度與鏈表實現的複雜度同樣爲1+log n或O(log n)。
  • 鏈表實現和數組實現的removeMin操做的複雜度同爲O(logn),
  • findMin 操做與鏈表實現的同樣, 其複雜度爲O(1)。

五、使用堆:堆排序

  • 使用一個堆來對某個數字列表進行排序,只需將列表的每元素添加到堆中, 而後一次一個地將它們從根中刪除。 在最小堆的情形下,排序結果將是該列表以升序排列。在最大堆的情形下,排序結果將是該列表以降序排列。
  • 對於堆的排序算法,咱們須要執行addElemcmt和removeElement兩個操做n次,即列表中每一個元素一次。 所以,最終的複雜度爲2XnXlogn,即O(nlog n)。

藍墨雲上作的一個練習就很清楚地顯示了這個過程。

算法

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

  • 問題1:課本屢次說到完成一些操做例如:addElement和removeMin等操做,數組和鏈表實現的堆的複雜度是相同的,可是仍是說數組實現的效率更高,這是爲何?數組和鏈表實現堆的優缺點分別是什麼?數組

  • 問題1解決方案:
    用數組實現堆時,進行addElement操做不須要和鏈表同樣從新肯定新節點雙親,removemin操做不須要肯定新的最末結點。數據結構

簡單總結一下,用數組實現堆的好處有學習

優勢:和順序存儲同樣的
一、能夠很方便找到孩子、雙親和兄弟,以及祖先和子孫
二、只須要存儲數據元素,不須要另外存儲元素的邏輯關係
三、物理結構和邏輯結構一致測試

  • 問題2:代碼解讀。下面這一段代碼是用鏈表實現堆的addElement操做時的返回插入結點雙親的那個節點的引用,可是我分狀況討論的過程當中一直出現理解不了的地方。
private HeapNode<T> getNextParentAdd()
    {
        HeapNode<T> result = lastNode;

        while ((result != root) && (result.getParent().getLeft() != result))
            result = result.getParent();

        if (result != root)
            if (result.getParent().getRight() == null)
                result = result.getParent();
            else
            {
                result = (HeapNode<T>)result.getParent().getRight();
                while (result.getLeft() != null)
                    result = (HeapNode<T>)result.getLeft();
            }
        else
            while (result.getLeft() != null)
                result = (HeapNode<T>)result.getLeft();
          
        return result;
    }
  • 問題2解決方案:第一遍看的時候,把本身的書畫的亂七八糟的都沒有理解這些代碼的意思,

而後就去問馨雨同窗,這些代碼的意思,結果討論討論着,馨雨馨雨就被我問蒙了,O(∩_∩)O,後來,發現是咱們理解錯了lastNode結點,「插入結點的雙親結點」,以前一直理解的是將要插入的結點的雙親結點,其實lastNode是最後一片葉子結點,狀況以下:

設計

代碼調試中的問題和解決過程

  • 問題1:

ArrayHeap類的代碼書上是有給出的,而後本身寫了一個測試類,結果發現出現了這樣的問題3d

  • 問題1解決方案:想要進行調試看一下,結果發現

    (這個問題我不知道是爲何發生的o(╥﹏╥)o)

而後又仔細思考了一下代碼,在代碼中將最後一個元素賦值給了root結點,可是緣由是並無將葉結點刪除,因此接下來從新調平衡的時候,最後的那個位置並進行操做,因此出現了重複。

代碼託管

(statistics.sh腳本的運行結果截圖)

上週考試錯題總結

  • 錯題1及緣由,理解狀況

    What type does "compareTo" return?
    A
    .
    int
    B
    .
    String
    C
    .
    boolean
    D
    .
    char

解析:compareTo()方法確實是String類中的一個,可是compareTo()的返回值是int。

它先比較對應字符的ASCII碼,如字符串的某字符與參數的某字符不等,則結束比較,返回它們ASCII碼的差值。直至字符串的字符或參數的字符 有一方全比較完,此時比較字符串的長度差並返回。

結對及互評

點評:

  • 本週結對學習狀況
  • 博客中值得學習的或問題:

    • 挺逗的,能夠用來吸引目光。博客的頁面又進行了修改,挺好看的。
  • 代碼中值得學習的或問題:
    • 設計的思路很清晰,不像我同樣老是很奇葩,^_^。

點評過的同窗博客和代碼

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

這周又是Java課多到爆表的雙週,咱們又開始完成實驗二了,並且這周老師還讓咱們組了個隊,要完成一個Java項目的開發,ε=ε=ε=(#>д<)ノ,難。
這個學期愈來愈注重代碼的編寫能力,也接觸到了不少的新的算法和知識點,就像這個禮拜學的堆,但願本身接下來的課程要繼續努力。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 10/10
第二週 326/326 1/2 18/28
第三週 784/1110 1/3 25/53
第四周 2529/3638 2/5 37/90
第五週 1254/4892 2/7 20/110
第六週 1403/6295 2/9 32/142
第七週 1361/7656 1/10 35/177
第八週 2750/10406 2/12 32/209
  • 計劃學習時間:30小時

  • 實際學習時間:32小時

  • 改進狀況:這周是雙週,Java課比較多,課程內容也比較多,保持了良好的學習進度和時間。

參考資料

相關文章
相關標籤/搜索