這還是個暖身的作業, 基本作法你在演算法的課程裡學過, 也會在實習時講一次, 不過這個作業開始有比較和物件相關的東西了, 主要要求你運用 C 的語法實作支援 Prim's Minimum Spanning Tree 演算法的 容器物件 - 抽象資料型態, 要求你運用課堂裡所解釋的函式指標來作出這個抽象資料型態, 同時也要求你這個容器物件需要使用上一次作業的 Heap 來提升效率。
因為在演算法課程裡學過這個程式, 所以應該不會有太大的心理負擔, 但是那時候有可能你沒有把精神用在寫一個別人很容易看得懂的程式, 沒有盡量用函式來抽象化程式的各個部份, 沒有把變數和函式好好取名字, 可能你沒有使用 MinHeap 來提昇容器的效率, 可能你沒有真的實作一個抽象資料型態, 只是用 C 的函式模擬需要有的功能, 沒有運用 assert 來確保各部份界面資料的正確性, 可能你沒有實作 adjacency matrix 的初始化, 可能沒有檢查你的程式是否有把所有動態配置的記憶體都釋放掉。這個作業裡希望你可以著重在這些部份, 當然如果你在上學期沒有寫出這個程式, 再給自己一次機會囉。
雖然不強制要求, 但是這個作業裡面的 adjacency matrix 你也可以把它變成一個 ADT, 你可以自己練習定義它的界面 (例如 getHead(vertex), next()), 如果你沒有時間完成這部份的話, 也可以留待下一個作業裡再完成。請注意, 雖然我們在課堂裡已經開始講 C++ class 的語法, 但是這個作業你需要用 C 的函式指標語法以及你在資料結構和演算法裡頭熟悉的 struct 來實作 ADT, 請你不要用 C++ 裡的 class 或是 struct 來實作, 那個是下一次的作業... 一個邏輯上幾乎一樣的作業可以交兩次, 很划算喔!
這個作業沒有提供範例執行程式, 針對程式執行的正確性, 需要你測試一些資料, 下面是三組基本的測試資料
參考執行結果(包含部份中間結果, 方便你檢查程式用的)
6 ; number of nodes 1..6 9 ; number of edges 1 2 4 ; edge (1,2), distance 4 1 3 2 ; edge (1,3), distance 2 1 5 3 2 4 5 . . .代表 Graph 中有 6 個節點 (編號為 1, 2, 3, 4, 5, 6), 9 個邊, 分別為 (節點1, 節點2) 邊長為 4, (節點1, 節點3) 邊長為 2, ...
prim(adj, start, parent) { n = adj.last for i = 1 to n key[i] = Infinite key[start] = 0 parent[start] = 0 h.init(key, n) for i = 1 to n { v = h.del() ref = adj[v] while (ref != null) { w = ref.ver if (h.isin(w) && ref.weight < h.keyval(w)) { parent[w] = v h.decrease(w, ref.weight) } ref = ref.next } } }這個演算法中逐步建構一個 MST, 演算法中的 for 迴圈每執行一次就由 h 中把一個最接近 "目前 MST" 的節點刪除, 並且加入 "目前 MST" 中; 這個 "目前 MST" 最後會記錄在 parent[] 陣列中, MST 的起點就是 start, parent[start] 設為 0, 代表它是 tree 的 root, 沒有任何父節點, 迴圈每執行一次, 概念上就把節點 v 加入 "目前 MST", 由於 "目前 MST" 多增加了這個節點, 所以 h 中與 v 相鄰的所有節點 w 到 "目前 MST" 的距離可能會有所改變同時 parent[w] 也會改變, 這是內層 while 迴圈的作用: 修改那些 h 中與 v 相鄰節點 w 的 parent[w] 以及 weight
struct Container { ... void (*init)(int [], int, struct Container *self); ... }; ... void initImplementation(int key[], int size, struct Container *self) { ... } ... struct Container h = {..., initImplementation, ...};上述函式定義中, 每一個函式的參數都需要多增加一個 struct Container *self 的參數,
int del(struct Container *self); int isIn(int w, struct Container *self); ...在 Prim 演算法裡呼叫 init() 時需要把 h.init(key, n); 改成 h.init(key, n, &h); 如果你這樣子實作這個 Container ADT 的話, 除了最後這個 self 參數之外, 你的 prim() 函式就和上面的演算法的 pseudocode 幾乎一樣了, 如果要完全一樣, 請使用 C++ 語法, 這是下一次的作業。
函式指標相關的練習請參考 (實習 3-2) [這學期因為放假所以跳過這個實習了]
再看一個 堆疊 的例子
回
C++ 程式設計課程
首頁
製作日期: 03/13/2012
by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw
TEL: 02 24622192x6615
海洋大學
電機資訊學院
資訊工程系
Lagoon