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

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

教材學習內容總結

第十二章 堆

堆:

堆是具備兩個附加屬性得的一棵二叉樹:html

  • 它是一棵徹底樹;
  • 對每一節點,它小(大)於或等於其左孩子和右孩子。

堆的分類:按照堆中元素排列規律將堆分爲兩類:node

  • 最小堆(minheap),本章介紹中默認的堆的類型,對每一節點,它小於或等於其左孩子和右孩子git

  • 最大堆(maxheap),與最小堆相反(對每一節點,它大於或等於其左孩子和右孩子)api

優先級隊列(priority queue):
排序規則:數組

  • 具備更高優先級的項在前;
  • 具備相同優先級的項目按照先進先出方法來肯定排序。

回顧知識點:徹底樹,樹最底層的葉子都在樹的左邊數據結構

堆接口的方法(最小堆)
| 操做 | 說明 |
|:---------:|:-------------------:|
|addElement | 將給定元素添加到該堆中 |
|removeMin | 刪除堆中的最小元素 |
|findMin | 返回一個指向堆中最小元素的引用 |學習

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

  1. 建立一個堆以後進行屢次addElement()操做添加元素後,還須要進行重排序?

選擇數組addElement()分析,較爲簡短:設計

public void addElement(T obj) 
    {
        if (count == tree.length)
            expandCapacity();

        tree[count] = obj;
        count++;
        modCount++;

        if (count > 1)
            heapifyAdd();
    }

    private void heapifyAdd()
    {
        T temp;
        int next = count - 1;
        
        temp = tree[next];
        
        while ((next != 0) && 
            (((Comparable)temp).compareTo(tree[(next-1)/2]) < 0))
        {
            tree[next] = tree[(next-1)/2];
            next = (next-1)/2;
        }

        tree[next] = temp;
    }

檢查代碼,發現:在插入過程當中addElement()方法引用了heapifyAdd()方法,addElement()方法僅做插入,將指定元素放到最末節點,若是不進行重排序,堆就不必定會符合小項在上的規則。調試

重排序和插入是同時進行的,而不是我以前理解的:先插入後排序code

一樣的問題,removeMin()方法刪除最小元素(最頂端),要維持堆的徹底性,替換它的元素是最末的元素,此時也須要進行重排序:

private void heapifyRemove()
    {
        T temp;
        int node = 0;
        int left = 1;
        int right = 2;
        int next;
        
        if ((tree[left] == null) && (tree[right] == null))
            next = count;
        else if (tree[right] == null)
            next = left;
        else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
            next = left;
        else
            next = right;
        temp = tree[node];

        while ((next < count) && 
            (((Comparable)tree[next]).compareTo(temp) < 0))
        {
            tree[node] = tree[next];
            node = next;
            left = 2 * node + 1;
            right = 2 * (node + 1);
            if ((tree[left] == null) && (tree[right] == null))
                next = count;
            else if (tree[right] == null)
                next = left;
            else if (((Comparable)tree[left]).compareTo(tree[right]) < 0)
                next = left;
            else
                next = right;
        }
        tree[node] = temp;
    }

removeMin()方法涉及到最末和頂部元素替換,重排序的過程也會相對複雜。


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

  1. 「既然用數組實現堆時,使用了數組進行儲存,爲何不能直接用這樣的方法來導入元素↓?」
public void ArrayToHeap(T[] array) {
        tree = array;
        count = tree.length + 1;
    }

後面產生了一系列問題,可是使用書本上的addElement()方法插入時則不會出錯,後來仔細研究addElement()才發現問題所在:直接導入的數組不必定符合堆的性質,而使用addElement()方法因爲重排序的存在能夠很好地解決這一問題。


代碼託管

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


上週考試錯題總結

  • Insertion sort is an algorithm that sorts a list of values by repetitively putting a particular value into its final, sorted, position.
    答案:false
    )並非直接放入最終排序位置。

  • There are only two ways that a tree, or any subtree of a tree, can become unbalanced: through the insertion of a node or through the deletion of a node.
    答案:true
    )書中原話。


學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 0/0 1/1 6/6
第二週 771/771 1/2 16/22
第三週 562/1233 1/3 15/37
第四周 1503/2736 2/5 15/52
第五週 1152/3888 1/6 10/62
第六週 787/4675 1/7 10/72
第七週 1214/5889 1/8 9/81
第八週 1534/7423 1/9 9/90

結對互評

唐才銘19
王文彬29

參考資料

相關文章
相關標籤/搜索