1. 程式人生 > >20172327 2018-2019-1 《程序設計與數據結構》第八周學習總結

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

復雜度 支持 詳細 ret dmi 第六周 useful 二叉 ren

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

教材學習內容總結

第十二章 優先隊列與堆



1.最小堆(minheap):對是一個完全二叉樹,其中的每個結點都小於或等於它的兩個孩子。

2.最大堆(maxheap):對是一個完全二叉樹,其中的每個結點都大於或等於它的兩個孩子。
技術分享圖片


3.最小堆將其最小的元素儲存在該二叉樹的根處,且其根的兩個孩子也同樣是最小堆

4.addElement操作
將元素添加為新的葉結點,同時保持樹是完全樹,將該元素向根的地方移動,將它與父結點對換,直到其中的元素大小關系滿足要求為止。

  • 在鏈表實現中:在鏈表實現中,添加元素時首先要確定插入結點的雙親。最壞的一種情況是從右下的最後一個葉子節點一直遍歷到根,在遍歷到堆的左下結點 。該過程的時間復雜度為2logn。下一步是插入節點(簡單的賦值,這裏的時間復雜度為O(1))。最後一步是將這棵樹進行重新排序。因為從根到結點的路徑長度為logn,所以最多需要進行logn此操作。因此使用鏈表實現時操作的復雜度為2*logn+1+logn。即O(logn)
  • 在鏈表實現中:在數組實現中,添加元素時並不需要確定新結點雙親的步驟,但是,其他兩個步驟與鏈表實現的一樣。因此,數組實現的addElement操作的時間復雜度為1+logn或O(logn)。雖然這兩者實現的復雜度相同,但數組實現的效率更高一些。


5.removeMin操作
利用最後的葉結點來取代根,然後將其向下移動到合適的位置。

  • 在鏈表實現中:removeMin必須刪除根元素,並用最後一個結點的元素來替換它(簡單的賦值,時間復雜度為O(1))。下面要對該樹進行重新排序,因為該樹原先是一個堆,所以只需要跟較小的一邊進行比較排序。因為從根到葉子的最大路徑長度為logn,因此該步驟的時間復雜度為O(logn)。到此時,這棵樹已經完成了,但在實際進行的過程中,為了繼續完成接下來的操作,我們還要找到新的最末結點,最壞的情況是進行叢葉子到根的遍歷,然後再從根往下到另一葉子的遍歷。因此,該步驟的時間復雜度為2logn。於是removeMin操作最後的時間復雜度為2logn+logn+1,即O(logn)。
  • 在數組實現中:removeMin也像鏈表實現的那樣,只不過它不需要確定最新的最末結點。因此,數組實現的removeMin操作的復雜度為logn+1。即O(logn)。


6.findMin操作
此操作較簡單,因為在添加元素的過程中就已經把最小元素移動到了根位置。


7.堆和二叉排序樹的區別:

  • 1.堆是一棵完全二叉樹,二叉排序樹不一定是完全二叉樹;
  • 2.在二叉排序樹中,某結點的右孩子結點的值一定大於該結點的左孩子結點的值,在堆中卻不一定;
  • 3.在二叉排序樹中,最小值結點是最左下結點,最大值結點是最右下結點。在堆中卻不一定。

堆的實現(以最大堆為例)


1.最大堆接口的實現:

public interface MaxHeap<T extends Comparable<T>> extends BinaryTree<T>
{
    //  Adds the specified object to the heap.
    public void add (T obj);

    //  Returns a reference to the element with the highest value in the heap.
    public T getMax ();

    //  Removes and returns the element with the highest value in the heap.
    public T removeMax ();
}


2.在 LinkedMaxHeap 中的 add 方法依賴於HeapNode中的兩個方法:getParentAdd 和 heapifyAdd 方法。
其中 getParentAdd 方法從樹的最後一個結點開始,一個一個檢測,尋找新加入結點的父結點。從樹中開始向上查找,直到發現它是某個結點的左子結點,或是到達根結點時為止。如果到達根結點,新的父結點是根的左後繼結點。如果沒有到達根結點,則再查找右子結點的最左後繼。刪除的成本。

public HeapNode<T> getParentAdd (HeapNode<T> last)
    {
        HeapNode<T> result = last;

        while ((result.parent != null) && (result.parent.left != result))
            result = result.parent;

        if (result.parent != null)
            if (result.parent.right == null)
                result = result.parent;
            else
            {
                result = (HeapNode<T>) result.parent.right;
                while (result.left != null)
                    result = (HeapNode<T>) result.left;
            }
        else
            while (result.left != null)
                result = (HeapNode<T>) result.left;

        return result;
    }

一旦新的葉結點添加到樹中,heapifyAdd 方法就利用 parent 引用沿樹向上移動,必要時交換元素。(交換的是元素,不是結點)

public void heapifyAdd (HeapNode<T> last)
    {
        T temp;
        HeapNode<T> current = last;

        while ((current.parent != null) &&
                ((current.element).compareTo(current.parent.element) > 0))
        {
            temp = current.element;
            current.element = current.parent.element;
            current.parent.element = temp;
            current = current.parent;
        }
    }

堆排序


1.思路:將一組元素一項項地插入到堆中,然後一次刪除一個。因為最大元素最先從堆中刪除,所以一次次刪除得到的元素將是有序序列,而且是降序的。同理,一個最小堆可用來得到升序的排序結果。
技術分享圖片

優先隊列


1.兩個規則:
1.具有更高優先級的項排在前.(不是FIFO)
2.具有相同優先級的項目按先進先出的規則排列。(FIFO)

2.實現方法:定義結點類保存隊列中的元素、優先級和排列次序。然後,通過實現 Comparable 接口定義 compareTo 方法,先比較優先級,再比較排列次序。

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

  • 問題1:對於堆排序的詳細步驟(具體順序)不清楚,教材上也只提供了思路。
  • 解決方案:
    【步驟一】構造初始堆,以大頂堆為例,給無序序列構造一個大頂堆,假設無序序列如下:
    技術分享圖片

從最後一個非葉子結點開始(葉結點不用調整,第一個非葉子結點 arr.length/2-1=5/2-1=1,也就是下面的6結點),從左至右,從下至上進行調整:
技術分享圖片

找到第二歌非頁結點4,由於[4、9、8]中9最大,4和9交換/
技術分享圖片

這時,交換導致了子根[4,5,6]結構混亂,繼續調整,[4,5,6]中6最大,交換4和6。
技術分享圖片

這樣大頂堆就完成了。
【步驟二】將堆頂元素與末尾元素進行交換,使末尾元素最大。然後繼續調整堆,再將堆頂元素與末尾元素交換,得到第二大元素。首先將堆頂元素9和末尾元素4進行交換:
技術分享圖片

重新調整結構,使其繼續滿足堆定義:
技術分享圖片

再將堆頂元素8與末尾元素5進行交換,得到第二大元素8:
技術分享圖片

【步驟三】如此反復進行交換、重建、交換。反復進行此過程,便可得到有序序列:
技術分享圖片

所以,基本步驟概括為:將無序堆構建成大頂堆或小頂堆,再通過反復交換堆頂元素和當前末尾元素並調整,最後使整個序列有序。

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

暫無

上周考試錯題總結

  • 錯題1.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
  • 分析:在從二叉查找樹中刪除元素時, 另一個節點必須促進以替換要刪除的節點。

  • 錯題2.The leftmost node in a binary search tree will contain the __________ element, while the rightmost node will contain the __________ element.
    A .Maximum, minimum
    B .Minimum, maximum
    C .Minimum, middle
    D .None of the above
  • 分析:二叉查找樹中最左邊的節點將包含最小元素, 而最右邊的節點將包含最大元素。

  • 錯題3.One of the uses of trees is to provide _________ implementations of other collections.
    A .efficient
    B .easy
    C .useful
    D .None of the above
  • 分析:樹的用途之一是提供其他集合的高效的實現。

  • 錯題4.The leftmost node in a binary search tree will contain the minimum element, while the rightmost node will contain the maximum element.
    A .True
    B .Flase
  • 分析:同錯題2。

  • 錯題5.One of the uses of trees is to provide simpler implementations of other collections.
    A .True
    B .Flase
  • 分析:同錯題3.

  • 錯題6.What type does "compareTo" return?
    A .int
    B .String

    C .boolean
    D .char
  • 分析:compareTo返回的是-1,0,1。所以為int值

  • 錯題7.Bubble, Selection and Insertion sort all have time complexity of O(n).
    A .true

    B .false
  • 分析:氣泡和插入排序都具有 o (n) 的時間復雜度,但選擇排序最好情況為O(n^2)。

  • 錯題8.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
  • 分析:插入排序在實現上,通常采用in-place排序(即只需用到O(1)的額外空間的排序),因而在從後向前掃描過程中,需要反復把已排序元素逐步向後挪位,為最新元素提供插入空間。

代碼托管

技術分享圖片

結對及互評

正確使用Markdown語法(加1分)
模板中的要素齊全(加1分)
教材學習中的問題和解決過程, (加3分)
代碼調試中的問題和解決過程, 無問題
感想,體會真切的(加1分)
點評認真,能指出博客和代碼中的問題的(加1分)

  • 20172317
    基於評分標準,我給以上博客打分:4分。得分情況如下:
  • 20172320
    基於評分標準,我給以上博客打分:8分。得分情況如下:

    • 結對學習內容
      • 教材第12章,運行教材上的代碼
      • 完成課後自測題,並參考答案學習
      • 完成程序設計項目:至少完成PP12.1、PP12.8、PP12.9

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

堆基於以前的所實現的,代碼需要補充的不多,所以還好學。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一周 0/0 1/1 8/8
第二周 1306/1306 1/2 20/28
第三周 1291/2597 1/3 18/46
第四周 4361/6958 2/3 20/66
第五周 1755/8713 1/6 20/86
第六周 3349/12062 1/7 20/106
第七周 3308/15370 1/8 20/126
第八周 4206/19576 2/10 20/146

參考:軟件工程軟件的估計為什麽這麽難,軟件工程 估計方法

  • 計劃學習時間:10小時

  • 實際學習時間:8小時

  • 改進情況:

(有空多看看現代軟件工程 課件
軟件工程師能力自我評價表)

參考資料

  • 《Java程序設計與數據結構教程(第二版)》

  • 《Java程序設計與數據結構教程(第二版)》學習指導
  • Java對象和引用變量
  • 為什麽Java不支持多重繼承

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