20172303 2018-2019-1《程式設計與資料結構》第9周學習總結
阿新 • • 發佈:2018-11-18
20172303 2018-2019-1《程式設計與資料結構》第9周學習總結
教材學習內容總結
常見的非線性結構有兩種——樹和圖,在經過了三週對樹的學習之後,本週我們接觸了另一種非線性結構圖的相關內容,包括圖的概念、圖的分類、圖的實現方法等。
一、圖的概述
- 概念:樹中的每個結點都只有一個父結點,如果我們允許一個結點連通多個其他結點,樹就變成了圖。
- 相關術語:
- 頂點(Vertex):圖中的資料元素。
- 邊(Edge):圖中各個頂點之間的連線。
- 鄰接/鄰居:兩個頂點之間有一條邊,則稱這兩個頂點是鄰接的。
- 路徑:連線兩個頂點之間的一系列邊稱為兩個頂點間的路徑,邊的條數稱為路徑長度(路徑長度=頂點數-1)。
- 環路:首頂點與末頂點相同且路徑中沒有邊重複的路徑。
- 例:
【圖】- 頂點:A,B,C,D
- 邊:(A,B)(A,C)(B,C)(B,D)(C,D)
- 鄰接:A與B是鄰接結點,A與D不是鄰接結點
- 路徑:A→D——(A,B)(B,C)(C,D) 路徑長度為3
- 環路:A→A——(A,B)(B,C)(C,A)
- 分類:
- 【是否有方向】無向圖和有向圖
- 【每條邊帶有權重或代價】加權圖/網路(加權圖可以是有向的也可以是無向的)
- 【特殊的圖】生成樹
1.無向圖
【圖】
- 無向圖是一種邊為無序結點對的圖。在無向圖中,(A,B)(B,A)指的是一條邊,表示A與B之間有一條兩個方向都連通
- 完全:一個無向圖是完全的,說明對於有n個頂點的無向圖,圖中有n(n-1)/2條邊。
- 連通:如果無向圖中的任何兩個頂點之間都存在一條路徑,則認為該無向圖是連通的。
- 同時連通還分為強連通和弱連通(非強連通),強連通圖中,任何兩個頂點之間都是連通的,就是說任何兩個頂點之間都至少有一條路徑。
- 完全圖一定是連通圖,連通圖不一定是完全圖。
- 無向樹:一種連通的沒有環路的,其中一個元素被指定為樹根的圖。
2.有向圖
- 有向圖/雙向圖是一種邊為有序頂點對的圖。在無向圖中,(A,B)(B,A)指的不是一條邊,(A,B)表示從A到B有一條連通的邊,但B到A沒有。
- 拓撲序:書上的說法是:“如果有向圖中沒有環路,且有一條從A到B的邊,則可以把頂點A安排在頂點B之前,這種排列得到的頂點次序稱為拓撲序”。說實話我看了七八遍也沒看懂這句話說的是什麼意思,後來上百度搜了一下,有了下面這張圖就很好理解了。【圖】
- 有向樹:其中一個元素被指定為樹根的有向圖稱為有向樹。
3.加權圖
- 加權圖/網路:是一種每條邊都帶有權重或代價的圖。加權圖中,某一條路徑的權重等於該路徑中所有邊權重的總和。【圖】
- 加權圖中邊的表示:在普通的圖中,我們表示邊時只需要起始頂點和終止頂點即可,但是在加權圖中,除了上面的兩項外還需要增加一個表示權重的元素。例如在有向圖中,從A到B之間有一條邊,權重為3,那麼它的表示就為(A,B,3)
4.生成樹
- 概念:一顆含有圖中所有頂點和部分邊的樹。一個圖的生成樹不一定是唯一的。
- 最小/大生成樹:樹中的路徑權重總和小於/大於它所來源的圖中的任何一顆生成樹的權重總和。
二、圖的演算法
(一)遍歷
- 圖的遍歷分為兩種:廣度優先遍歷(簡稱BFS,與樹中的層序遍歷類似)深度優先遍歷(簡稱DFS,與樹中的前序遍歷類似)。
- 廣度優先遍歷——使用一個佇列和一個無序列表來實現,佇列用於管理遍歷,無序列表用於儲存遍歷結果。
- 第一步:起始頂點進入佇列,標記為已訪問。
- 第二步:從佇列中取出起始頂點加入無序列表的末端,讓與該頂點相連的還未被標記為已訪問的頂點加入佇列中,把它們都標記為已訪問。
- 第三步:重複第二步的操作,每次取出佇列中的首個頂點加入無序列表,直至佇列為空。
- 深度優先遍歷——使用一個棧和一個無序列表來實現,棧的作用與廣度優先遍歷中佇列的作用相同。
- 第一步:起始頂點進入棧。
- 第二步:從棧中取出起始頂點加入無序列表的末端,標記為已訪問,讓與該頂點相連的頂點加入棧中。
- 第三步:重複第二步的操作,每次取出棧頂元素加入無序列表,把頂點標記為已訪問,直至棧為空。
- 例項【圖】
- 廣度優先遍歷(書上有詳細過程,就不在此詳列了):9、6、7、8、3、4、5、1、2
- 深度優先遍歷:9、8、5、1、4、2、3、7、6【圖】
(二)測試連通性
- 要判斷一個圖的連通性,需要確定圖中的任意兩個頂點之間都有一條路徑,如果直接判斷的話時間複雜度會很大。書上給出了一種簡單的判斷方法:在一個含n個頂點的圖中,當且僅當圖中的每個頂點的廣度優先遍歷的無序列表長度都為n時,證明該圖就是連通的。
(三)最小生成樹
- 推衍演算法(以最小生成樹為例):在尋找最小樹的過程中需要一個最小堆用於每次尋找最小邊
- (1)從圖中任選一個起始頂點,將它新增到最下生成樹中
- (2)將所有含起始頂點的邊按照權重由小到大的順序加入到最小堆中
- (3)從最小堆中選出權重最小的邊,將該邊和與該邊連線的最小生成樹中沒有的頂點加入最小生成樹中,加入的頂點成為新的起始頂點。
- (4)重複第二和第三步直至最小生成樹中含有圖的所有頂點或最小堆為空時。
(四)判斷最短路徑
- 情況一:最短路徑為兩個頂點之間的最小邊數
- 這種情況下將廣度優先遍歷進行修改即可實現,修改方式為在遍歷的過程中增加兩個資訊:從起始頂點到遍歷到該頂點的路徑長度,以及路徑中該頂點的前驅結點。
- **
教材學習中的問題和解決過程
- 問題1:
- 問題1解決方案:
- 問題2:
- 問題2解決方法:
- 問題3:
- 問題3解決方法:
程式碼除錯中的問題和解決過程
- 問題1:
- 問題1解決方法:
- 問題2:
- 問題2解決方法:
程式碼託管
上週考試錯題總結(正確為綠色,錯誤為紅色)
上週沒有測試。
結對及互評
點評模板:
- 部落格中值得學習的或問題:
- 優點:本週的部落格大有長進!內容豐富了很多,終於做到了圖文並茂,值得誇獎!
- 問題:圖片的排版還需加強。
- 程式碼中值得學習的或問題:
- 優點:提了幾周的commit提交終於有所改進,感覺這周我的搭檔有了質的飛躍。
可能是一遍遍的吐槽起了作用,果然像馬原老師說的一樣,量變會引起質變! - 問題:本週程式碼的備註不是很多。
- 優點:提了幾周的commit提交終於有所改進,感覺這周我的搭檔有了質的飛躍。
點評過的同學部落格和程式碼
- 本週結對學習情況
- 20172322
- 結對學習內容
- 給我講解了課堂實驗ASL計算的方法。
- 主要探討了歸併排序的計數方法。
## 其他(感悟、思考等,可選)
學習進度條
程式碼行數(新增/累積) | 部落格量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 10/10 | 1/1 | 10/10 | |
第二週 | 246/366 | 2/3 | 20/30 | |
第三週 | 567/903 | 1/4 | 10/40 | |
第四周 | 2346/3294 | 2/6 | 20/60 | |
第五週 | 2346/3294 | 2/8 | 30/90 | |
第六週 | 1343/4637 | 2/8 | 20/110 | |
第七週 | 654/5291 | 1/9 | 25/135 | |
第八週 | 2967/8258 | 1/10 | 15/150 | |
第九周 | 2967/8258 | 2/12 | 15/150 |
計劃學習時間:20小時
實際學習時間:30小時
改進情況:本週的大部分時間基本都花在了對於查詢演算法和排序演算法的理解上了,感覺對時間複雜度理解和計算的應用變得更加熟練了。