20172316 2018-2019-1《程式設計與資料結構》第九周學習總結
20172316 2018-2019-1《程式設計與資料結構》第九周學習總結
教材學習內容總結
第十五章 圖
圖:
堆是具有兩個附加屬性得的一棵二叉樹:
- 它是一棵完全樹;
- 對每一節點,它小(大)於或等於其左孩子和右孩子。
堆的分類:按照堆中元素排列規律將堆分為兩類:
最小堆(minheap),本章介紹中預設的堆的型別,對每一節點,它小於或等於其左孩子和右孩子
最大堆(maxheap),與最小堆相反(對每一節點,它大於或等於其左孩子和右孩子)
優先順序佇列(priority queue):
排序規則:
- 具有更高優先順序的項在前;
- 具有相同優先順序的專案按照先進先出方法來確定排序。
回顧知識點:完全樹,樹最底層的葉子都在樹的左邊
堆介面的方法(最小堆)
| 操作 | 說明 |
|:---------:|:-------------------:|
|addElement | 將給定元素新增到該堆中 |
|removeMin | 刪除堆中的最小元素 |
|findMin | 返回一個指向堆中最小元素的引用 |
教材學習中的問題和解決過程
- 建立一個堆之後進行多次
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()
方法僅作插入,將指定元素放到最末節點,如果不進行重排序,堆就不一定會符合小項在上的規則。
重排序和插入是同時進行的,而不是我之前理解的:先插入後排序
同樣的問題,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()方法涉及到最末和頂部元素替換,重排序的過程也會相對複雜。
程式碼除錯中的問題和解決過程
- “既然用陣列實現堆時,使用了陣列進行儲存,為什麼不能直接用這樣的方法來匯入元素↓?”
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 |
結對互評
參考資料
- 《Java程式設計教程(第八版)》電子工業出版社
- 《使用碼雲和部落格園學習簡易教程》
- 《使用開源中國(碼雲)託管程式碼》
- 資料結構(一) 單鏈表的實現-JAVA