20172323 2018-2019-1 《程序設計與數據結構》第八週學習總結

20172323 2018-2019-1 《程序設計與數據結構》第八週學習總結

教材學習內容總結

本週學習了第12章優先隊列與堆php


  • 12.1 堆
  • 堆是具備兩個附加屬性的一棵二叉樹,它是一棵徹底樹,對於每一結點,它小於或等於其左孩子和右孩子,這樣定義下的堆是最小堆,若是對於每一結點,它大於或等於其左孩子和右孩子,那麼它就是最大堆。
  • 最小堆將其最小元素存儲在該二叉樹的根處,且其根的兩個孩子一樣也是最小堆。
操做 說明
addElement 將給定元素添加到該堆中
removeMin 刪除堆的最小元素
findMin 返回一個指向堆中最小元素的引用
  • 如圖是一個最小堆
    html

  • addElement方法將給定的Comparable元素添加到堆中的恰當位置處,且維持該堆的徹底性屬性和有序性屬性node

    若是一棵二叉樹是平衡的,及全部葉子都位於h或者h-1層,其中h爲log2n,n是樹中的元素數目,以及全部h層中的葉子都位於該樹的左邊,那麼該樹就被認爲是徹底的。由於堆是一棵徹底樹,因此對於新插入的結點只存在一個正確的位置,要麼是h層左邊的下一個空位置,要麼就是h+1層左邊的第一個位置(若是h層是滿的話)git

  • 新結點添加以後,將考慮堆的排序性。,該結點將於它的雙親結點進行比較,若是新結點小則要與雙親結點進行互換,以後再沿樹往上進行比較直至新值大於雙親或者位於根結點。
  • 在堆實現中,咱們會對樹中的最末一個結點(最末一片葉子)進行跟蹤記錄。

    2添加到堆以後,將於其雙親進行比較上浮直至堆知足其順序屬性
  • removeMin操做將刪除最小堆中的最小元素並返回他,最小堆中的元素便是它的根結點,爲了保持樹的合法性,須要有一個能替換根的合法元素,且它是樹中最末一片葉子上的元素。將最末一片葉子移至根處以後,又須要將該堆進行從新排序。排序方法須要將該結點與最小孩子進行比較而後逐漸下沉到合適的位置。借用上圖,若是將根結點1刪去,那麼最末葉子6就將成爲新的根結點,它將與二、5進行比較最終落在5如今的位置,而2將成爲新的根結點。web


  • 12.2 使用堆:優先級隊列
  • 優先級隊列就是遵循兩個排序規則的集合。一是具備更高優先級的項目在先,二是具備相同優先級的項目使用先進先出方法肯定其排序。
  • 雖然最小堆根本就不是一個隊列,可是他卻提供了一個高效的優先級隊列實現

  • 12.3 用鏈表實現堆
  • 堆中結點必須存儲指向其雙親的指針。
  • 鏈表實現addElement操做的時間複雜度爲O(logn)
  • removeMin操做的時間複雜度一樣爲O(logn)。
  • findMin操做時間複雜度爲O(1)

  • 12.4 用數組實現堆
  • 堆的數組實現比鏈表實現更爲簡潔。
  • 在二叉樹的數組實現中,樹的根位於位置0處,對於每一結點n,n的左孩子將位於數組的2n+1
    處,n的右孩子將位於數組的2(n+1)位置處
  • 數組實現不須要肯定新結點雙親,時間複雜度與鏈表實現相同,但數組實現效率更高
  • 鏈表實現與數組實現的removeMin操做的複雜度同爲O(logn)

  • 12.5 使用堆:堆排序
  • 堆排序的由兩步構成:添加列表的每一個元素,而後一次刪除一個元素
  • 堆排序的複雜度爲O(nlogn)

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

  • 問題1:鏈表實現堆的過程當中的addElement操做第一步要肯定要插入結點的雙親,爲何在最壞的狀況下要從堆的右下結點遍歷到根結點以後還要再從根結點遍歷到堆的左下結點?數組

  • 問題1解決方案:這個問題我思考了小半個小時,添加的第一步須要肯定插入結點的雙親,由於須要比較雙親結點的值與新結點的值,決定新結點是否要上浮。因此最壞的狀況應該是新結點一直上浮到根結點,此時按最小堆的定義來看,添加元素這一操做應該是中止了,由於堆頂是最小元素了,它的左孩子和右孩子的值都應該比它要小,因此不須要繼續遍歷它的左孩子直到左下結點了吧。和同窗討論以後,才發現個人理解錯在哪裏了。它這裏指的是遍歷的最壞狀況須要從右下結點一直到根再到左下結點,而不是結點互相之間的比較須要讓結點上浮以後再次下沉(事實上跟我分析的同樣,他也沒法作到)。它這裏指的是查找肯定新結點的雙親結點的最壞狀況

    如上醜圖,添加元素時恰好碰見滿樹的狀況,須要從右下最後一片葉子開始找起,一直到左下結點,才最終肯定要插入的元素的雙親結點。數據結構


  • 問題2:對書上代碼getNextParentAdd方法的理解
  • 問題2解決方案
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;

首先教材講到,這是一個返回指向插入結點的雙親結點的引用。因此就容易理解到,這個方法就是肯定新插入結點的雙親結點。也就經過此來決定新添加元素的位置。
一開始,新設一個變量result指向lastNode,即指向最後一片葉子的引用。
接下來經過判斷最後一片葉子的狀況來肯定插入結點的雙親結點,當最後一片葉子不是根結點且同時不是左孩子的時候,就將result的父結點付給result,直到不知足兩個條件之一跳出循環。當最後一片葉子是根結點時,已經肯定了新結點的雙親結點,能夠進入下一步,而若是最後一片葉子是右結點,就說明當前父結點是滿的,不能再在當前父結點下添加新元素,因此將result指向result的父親,方便尋找一個沒有滿的父結點。下一步,此時result跳出while循環,要麼它是根結點,要麼它是左孩子。若是它是左孩子,即進入if語句內,判斷它的兄弟結點是否爲null,若是返回true,那麼新添加元素的雙親結點就肯定了是result的父結點,而新結點將做爲result的右孩子添加到堆中,若是返回false,result將指向這個右孩子,並找到它的最左下的位置添加。若是result是指向根結點的,那麼也一直循環到它的最左下位置,添加新元素。
這個問題的解決參考了於欣月同窗的博客,她在解釋時運用了圖文結合的形式,對我理解該問題起了很大幫助ide


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

  • 問題1:測試LinkedHeap類,實現層序輸出、前序中序後序各類輸出,很不巧的是它出現了亂碼的狀況
    學習

  • 問題1解決方案:這個問題的出現充分說明我還沒能掌握迭代器的精髓,首先方法的使用就是徹底錯誤的,我還把它看成簡單的toString方法在加以使用。因此天然輸出不來須要的結果,標準的應該是如圖,先設置一個迭代器的對象,經過for循環一個一個調用迭代器裏的內容,如圖
    測試

代碼託管

上週考試錯題總結


  • In removing an element from a binary search tree, another node must be ___________ to replace the node being removed.
    A .duplicated
    B .demoted
    C .promoted
    D .None of the above
  • 解析:從二叉查找樹中刪除一個元素時,必須推選出另外一個結點來代替要被刪除的那個結點
    。demoted意思是降級的,promoted是升級的,從概念來看,替代元素應該是該結點的中序後繼者,因此該是c。

  • The Java Collections API provides two implementations of balanced binary search trees, TreeSet and TreeMap, both of which use a ___________tree implementation.
    A .AVL
    B .red/black
    C .binary search
    D .None of the above
  • 這好像是13章的內容亂入了吧,TreeSet和TreeMap類使用的是紅黑平衡二叉查找樹

  • The best comparison sort in terms of order is:
    A .O(1)
    B .O(n)
    C .O(log(n))
    D .O(nlog(n))

  • Linear search has logarithmic complexity, making it very efficient for a large search pool.
    A .true
    B .false
  • 線性查找具備線性時間複雜度O(n)。

  • Bubble, Selection and Insertion sort all have time complexity of O(n).
    A .true
    B .false
排序方法 時間複雜度
選擇排序 O(n^2)
插入排序 O(n^2)
冒泡排序 O(n^2)

  • Insertion sort is an algorithm that sorts a list of values by repetitively putting a particular value into its final, sorted, position.
    A .true
    B .false
  • 插入排序經過反覆地將某一特定值插入到該列表的某個已排序的子集中來完成對列表值的排序。每個值只須要插入一次,而不是重複地插入。

結對及互評

  • 博客中值得學習的或問題:
    • 在個人鞭策與督促之下,某同窗的博客又恢復到了以往的超高水平。(他在教材問題中提到了一個

      實現優先級隊列的二叉堆、d堆、左式堆、斜堆、二項堆都是什麼意思?

我翻了一下書,好像沒有找到哪裏提到了這些概念,因此若是是查找的資料裏提到的,但願也能貼出連接來,讓我學習學習,不至於落下太多

  • 方藝雯的博客寫的很棒,提出了不少我沒考慮過的問題。

  • 基於評分標準,我給譚鑫的博客打分:6分。得分狀況以下:
    正確使用Markdown語法(加1分)
    模板中的要素齊全(加1分)
    教材學習中的問題和解決過程, 一個問題加1分
    代碼調試中的問題和解決過程, 三個問題加3分

  • 基於評分標準,我給方藝雯的博客打分:8分。得分狀況以下
    正確使用Markdown語法(加1分):
    模板中的要素齊全(加1分)
    教材學習中的問題和解決過程, 兩個問題加2分
    代碼調試中的問題和解決過程, 四個問題加4分

  • 本週結對學習狀況
  • 上週博客互評狀況

其餘

這周的教材學習比較容易,因此花的時間相對較少,可是實驗使人難受。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 0/0 1/1 8/8
第二週 470/470 1/2 12/20
第三週 685/1155 2/4 10/30
第四周 2499/3654 2/6 12/42
第六週 1218/4872 2/8 10/52
第七週 590/5462 1/9 12/64
第八週 993/6455 1/10 12/76
第九周 1192/7467 2/12 10/86

參考資料

相關文章
相關標籤/搜索