20172310 2017-2018《程序設計與數據結構》(下)第九周學習總結

20172310 2017-2018《程序設計與數據結構》(下)第九周學習總結

教材學習內容總結

這一章又要學習一個新的體系了——圖html

無向圖、有向圖和網絡

接下來的例子都是使用這兩個圖
java

一些共同的基礎概念git

  • 頂點:結點,通常用名字和標籤來表示,如A、B等。
  • 邊:節點之間的鏈接,用結點對來表示,如A、B頂點間的一條邊(A,B)。
  • 鄰接:若是圖中的兩個頂點之間有一條連通邊,則稱這兩個頂點是鄰接的,如圖中AB鄰接,A、D不鄰接。
  • 自循環 :連通一個頂點及其自身的邊稱爲自循環或環, 例如,邊(A,A) 表示的是鏈接A到自身的一個環。算法

  • 路徑: 無向圖中是指圖中的一系列邊,每條邊連通兩個頂點。例如,圖1,ABD就是一條從A到D的路徑。有向圖中的路徑是圖中連通兩個頂點的有向邊序列。數組

無向圖中的路徑是雙向的。例如,ABD確實是從A到D的路徑,但因爲這些邊並無方向,所以反過來,DBA又是從D到A的路徑。網絡

  • 路徑的長度:是該路徑中邊的條數(或者是頂點數減去1)。如,從A到D的路徑長度是2。注意, 這裏對路徑長度的定義等同於討論樹時用到的路徑長度定義,由於, 樹也是圖的一種。數據結構

  • 環路:是一種首頂點和末頂點相同且沒有重邊的路徑。在圖1中,咱們稱路徑ABCA是一條環路。沒有環路的圖稱爲無環的。函數

  • 連通:在無向圖中,若是其中的任意兩個頂點之間都存在一條路徑,則認爲這個無向圖是連通的(connected),連通有向圖的定義聽起來和連通無向圖的定義同樣。若是有向圖中的任意兩個頂點之間都存在一條路徑, 則認爲該有向圖是連通的。可是記住,對有向圖和無向圖的路徑定義是不一樣的。
    學習


無向圖測試

  • 定義:無向圖(undirected graph)是一種邊爲無序結點對的圖。記做(A, B)的邊就意味着A與B之間有一條從兩個 方向均可以遊歷的鏈接 ,(A,B) 和記做(B,A) 的含義是徹底樣的。

  • 若是無向圖擁有最大數目的連通頂點的邊,則認爲這個無向圖是徹底的。也就是說,對於第一個頂點,須要(n一1)條邊將其與其餘頂點連通。對於第2個頂點,只需(n-2)條邊(除去與第一個頂點相連的邊)。第三個頂點須要 (n-3)條邊。 因此,對有n個頂點的無向圖,要使該圖爲徹底的,要求有n(n- 1)/2條邊。注意,這裏假設其中沒有邊是自循環的。

  • 無向樹(undirected tree)是一種連通的無環無向圖,其中一個元素被指定爲樹根。


有向圖

  • 有向圖(directed graph)有時也稱爲雙向圖(digraph),它是一種邊爲有序頂點對的圖。這意味着邊(A,B) 和邊(B, A)在有向圖中是不一樣的有向邊。

  • 若是有向圖中沒有環路,且有一條從A到B的邊,則能夠把頂點A安排在頂點B以前。這種排列獲得的頂點次序稱爲拓撲序(lopological order)

  • 有向樹是種指定了個元素做爲樹根的有向圖,還有以下屬性:

    • 不存在其餘頂點到樹根的鏈接。

    • 每一個非樹根元素剛好有一個鏈接。

    • 樹根到每一個其餘頂點都有一條路徑。


網絡

  • 網絡(network),或稱爲加權圖(weighted graph),是一種每 條邊都帶有權重或代價的圖。網絡能夠是無向的,也能夠是有向的,知足有向圖或無向圖的性質。一般,咱們用一個三元組來表示每條邊。,這個三元組中包括起始頂點、 終止項點和權重。記住,對無向網絡來講,起始頂點與終止頂點能夠互換。但對有向圖來講,必須包含每一個有向鏈接的三元組。

(這是一個網絡,該網絡描繪了在美國城市之間的連通性和飛機票價。這個加權圖(或網絡)能夠用於肯定從個城市到另外一個城市的最便宜行程。)

  • 加權圖中的路徑權重是該路徑中各條邊權重的和。

圖的經常使用算法

在這裏咱們學習的算法包括:各類遍歷算法(這些遍歷相似於探討過的樹遍歷),尋找最短路徑的算法,尋找網絡中最低代價路徑的算法,回答一些簡單圖相關問題(例如,圖是不是連通的,圖中兩個頂點間的最短路徑是什麼,等等)的算法。


遍歷

  • 圖的遍歷分紅兩類(注意,圖中不存在根結點,所以圖的遍歷能夠從其中的任頂點開始):
    • 廣度優先遍歷(breadth-first traversal),相似於樹的層次遍歷

課本中用一個隊列和一個無序列表來構造圖的廣度優先遍歷。咱們將使用隊列(traversalQueue)來管理遍歷,使用無序列表(resultList) 來構造出結果。
用一個實例來講明:


(1)往traversalQucue中添加9,而且把它標記爲visited.
(2)從traversalQucuc中取出9.
(3)往resultList中添加9.
(4)往traversalQucue中添加六、7和8,網時把它們逐 標記爲visited.
(5)從traversalQueuc中取出6。
(6)往resultList中添加6。
(7)往raversalQucue中添加三、4,同時把這兩個頂點標記爲vsited.
(8)從traversalQueue中取出7,並將它添加到resutList中。
(9)往traversalQueue中添加5,而且把它標記爲visited.
(10)從traversalQueure中取出8,並將它添加到resutList中(這時再也不往traversal.Qucue中添加任何新的頂點,由於頂點8再也沒有還沒有訪問過的鄰居了).
(11)從traversalQueuc中取出3,並將它添加到resultList中。
(12)往traversalQueue中添加1,而且把它標記爲visited.
(13)從traversalQueue中取出4,並將它添加到resultList中。
(14)往traversalQueue中添加2,而且把它標記爲visited.
(15)從traversalQueue中取出5,並將它添加到resultList中(因爲再也沒有未訪問過的鄰居,所以不需再往traversalQueue中添加頂點)。
(16)從traversalQueue中取出1,並將它添加到resultList中(因爲再也沒有未訪問過的鄰居,所以不需再往traversalQueue中添加頂點)。
(17)從traversalQucue中取出2,並將它添加到resultList中。
這樣,resultList 就以廣度優先次序存放了從頂點9開始的以下頂點: 九、六、七、八、三、四、五、1和2。

  • 深度優先遍歷(depth-first traversal),相似於樹的前序遍歷

圖的深度優先遍歷構造使用了一樣的邏輯,只不過在深度優先遍歷中用traversalStack代替了traversalQueue可是, 算法中還有一處不一樣:在頂點還沒有添加到resultList以前,咱們並不想標記該項點爲visited.


測試連通性

  • 關鍵思想:不論哪一個爲起始頂點,當且僅當廣度優先遍歷中的頂點數目等於圖中的頂點數目時,該圖纔是連通的。

最小生成樹

  • 生成樹(spanningtree)是一棵含有圖中全部頂點和部分邊(但可能不是全部邊)的樹。

  • 最小生成樹(minimum spanningtree, MST)是加權圖的最小生成樹,它是一棵生成樹, 其邊的權重總和小於或等於同一個圖中其餘任何一棵生成樹的權重總和。

  • 算法:任意選取個起始頂點(無論是哪個), 並將它添加到最小生成樹中。而後,將全部含該起始頂點的邊按照權重次序添加到minheap (最小堆)中。(若是處理的是有向網絡,則只會添加那些以這個特定頂點爲起點的邊。)接着從minheap中取出最小邊,並將這條邊和那個新頂點添加到最小生成樹中。下一步,咱們往minbeap中添加全部含該新頂點的另外一頂點尚不在最小生成樹中的邊。繼續這過程,直到最小生成樹含有原始圖中的全部頂點(或minheap爲空)時結束。


斷定最短路徑

  • 斷定圖的「最短」路徑有兩種狀況。
    • 第一種, 斷定起始頂點與目標頂點之間的字面意義上的最短路徑,也就是兩個頂點之間的最小邊數。能夠將廣度優先遍歷算法轉變成尋找最短路徑的算法,只需在遍歷期間再對每一個頂點存儲另兩個信息便可:從起始頂點到本頂點的路徑長度,以及路徑中做爲本項點前驅的那個頂點。接着要修改循環,使得當抵達目標頂點時循環將終止。最短路徑的路徑長度就是從起始頂點到目標頂點前驅的路徑長度再加1;若是要輸出這條最短路徑上的頂點,只需沿着前驅鏈回溯便可。
    • 斷定最短路徑的第二種狀況是,尋找加權圖的最便宜路徑。用一個minheap或優先隊列來存儲頂點,基於總權重(從起始頂點到本頂點的權重和)來衡量頂點對,這樣咱們老是能優先沿着最便宜的路徑來遊歷圖。對每一個頂點都必須存儲該頂點的標籤,(迄今爲止)從起始頂點到本頂點的最便宜路徑的權重,路徑上本頂點的前驅。在minheap中將存儲頂點、對每條已經遇到但還沒有遊歷的候選路徑來權衡頂點對。從minheap取出頂點的時候,會權衡取自minheap 的頂點對:若是遇到一個頂點的權重小於目前本頂點中已存儲的權重,則會更新路徑的代價。

圖的實現策略

  • 鄰接列表:對圖結點來講,因爲每一個結點能夠有多達n-1條邊與其餘結點相連,所以最好用種相似於鏈表的動態結點來存儲每一個結點帶有的邊。這種鏈表稱爲鄰接列表(adjacency is)。對網絡或加權圖而言,每條邊會存儲成一個含權重的三元組。對無向圖而言,邊(A,B)會同時出如今頂點A和頂點B的鄰接列表中。

  • 鄰接矩陣:鄰接矩陣(adjacency matrix) 是一個二維數組。在鄰接矩陣中,這個二維數組中的每一個單元都表示了圖中兩個頂點的交接狀況。對矩陣中的任何單元(row, colum)而言,當且僅當圖中存在(Vrow,Vcolum)時,這個單元才爲true。因爲無向圖中的邊是雙向的,所以,若是(A, B)是圖中的一條邊,那麼(B,A)一樣也是圖中的一條邊。


(注意,這個矩陣是對稱的,即該矩陣對角線的一側是另外一 側的鏡像。 其緣由就在於它所表示的是個無向圖。 對無向圖來講,沒有必要表示整個矩陣,只需給出矩陣對角線的一側(或另外一側)便可。)

用鄰接矩陣實現無向圖

點擊查看代碼實現

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

  • 問題1:教材中講述遍歷的時候只詳細介紹了廣度優先遍歷,和給出了深度優先遍歷的代碼,那深度優先遍歷的狀況是怎樣的呢?並且遍歷都是以無向圖來講明的,可是若是有向圖又該是什麼樣的狀況呢?

  • 問題1解決方案:
  • 廣度優先遍歷在上面的教材總結中已經詳細的介紹過一下流程
  • 深度優先遍歷的狀況

有向圖的遍歷其實就是看圖是不是連通的,看網上的這幅圖

他的深度優先遍歷狀況就應該是:

第1步:訪問A。
第2步:訪問B。
在訪問了A以後,接下來應該訪問的是A的出邊的另外一個頂點,即頂點B。
第3步:訪問C。
在訪問了B以後,接下來應該訪問的是B的出邊的另外一個頂點,即頂點C,E,F。在本文實現的圖中,頂點ABCDEFG按照順序存儲,所以先訪問C。
第4步:訪問E。
接下來訪問C的出邊的另外一個頂點,即頂點E。
第5步:訪問D。
接下來訪問E的出邊的另外一個頂點,即頂點B,D。頂點B已經被訪問過,所以訪問頂點D。
第6步:訪問F。
接下應該回溯"訪問A的出邊的另外一個頂點F"。
第7步:訪問G。
所以訪問順序是:A -> B -> C -> E -> D -> F -> G

他的廣度優先遍歷狀況就應該是:

第1步:訪問A。
第2步:訪問B。
第3步:依次訪問C,E,F。
在訪問了B以後,接下來訪問B的出邊的另外一個頂點,即C,E,F。前面已經說過,在本文實現中,頂點ABCDEFG按照順序存儲的,所以會先訪問C,再依次訪問E,F。
第4步:依次訪問D,G。
在訪問完C,E,F以後,再依次訪問它們的出邊的另外一個頂點。仍是按照C,E,F的順序訪問,C的已經所有訪問過了,那麼就只剩下E,F;先訪問E的鄰接點D,再訪問F的鄰接點G。
所以訪問順序是:A -> B -> C -> E -> F -> D -> G

你們也能夠參考一下這篇資料圖的遍歷之 深度優先搜索和廣度優先搜索

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

  • 問題1:編寫pp15.1即用鄰接列表實現無向圖最難的在我看來是遍歷的書寫。

  • 問題1解決方案:以前我找百度,看見裏面的寫法不少都是直接調用了Java類庫中的ArrayList類,我也找同窗幫助看了看他們編寫的思路,也有用了類庫的那樣他們的遍歷方法能夠繼續使用原來的不用從新編寫,可是我以爲那個本質上使用的只是數組套數組,並無鏈表的影子。我還看到了另外一種寫法,就是使用本身當初編寫的指針類,像是這樣的。

因此我想直接使用咱們當初編寫的LinearNode類,這樣就像咱們以前學習到的哈希函數的編寫方法,可是這時的遍歷方法就要改寫。
對原來的代碼進行了改寫代碼連接

  • 問題2:

  • 問題2解決方案:最近的的調試老是出現這樣的問題,看樣子是要解決一下了

(我以前還覺得是當初的那個代碼寫的有問題,如今才發現看樣子是有哪裏出問題了,否則之後都調試不了了)

其實個人編寫思路是和馨雨同窗同樣的,和她同樣在寫添加邊的過程當中出現了越界的問題,我思考了好久都沒有想出是爲何(我以爲本身的思路沒有問題TAT),而後就去參考了一些同窗們的寫法,最後屈服了,換了一種寫法。

代碼託管

上週考試錯題總結

  • 錯題1及緣由,理解狀況

「由於堆是二叉搜索樹,因此只有一個正確的位置用於插入新節點,而且若是級別h已滿,該位置能夠是從級別h左側的下一個打開位置或在級別h+1左側的第一個打開位置。」
這道題會錯是由於本身只注意到了後面的講述是對的,沒看到最關鍵的前提 堆是一棵徹底樹,纔有後面的內容。

結對及互評

點評:

  • 本週結對學習狀況
  • 博客和代碼中值得學習的或問題:
    • 教材和代碼問題的總結很好。那些算法我都只是進行了粗略的理解,不像隊友同樣認真的總結了,值得學習。
    • 代碼問題遇到了也都相應的進行了解決,而不是像我解決不了這個問題,就只好換一個寫法,要多像隊友討教編寫的思惟,多多地練習。

點評過的同窗博客和代碼

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

又是緊張的一週學習,其實這周的做業是上次做業都還沒完成的狀況下就發佈了的,但仍是時間緊張呀。這周其實課本
上給出的代碼不算多,因此代碼做業就看起來挺多的。時光匆匆,貌似咱們這一本課本也學習完了(其實仍是沒有吃透(つД`)),
立刻又要開始魔鬼般的實驗做業了,但願我不會給個人小夥伴們拖後腿了。

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積)
目標 5000行 30篇 400小時
第一週 0/0 1/1 10/10
第二週 326/326 1/2 18/28
第三週 784/1110 1/3 25/53
第四周 2529/3638 2/5 37/90
第五週 1254/4892 2/7 20/110
第六週 1403/6295 2/9 32/142
第七週 1361/7656 1/10 35/177
第八週 2750/10406 2/12 32/209
第九周 2444/12850 1/13 23/232
  • 計劃學習時間:25小時

  • 實際學習時間:23小時

參考資料

相關文章
相關標籤/搜索