圖的概念有點多,在此只討論最基礎的內容,因此選擇比較薄的高教版《數據結構》。html
1.4 非線性數據結構--圖 ........................................................................................................... 101 1.4.1 圖的基本概念.............................................................................................................. 102 1.4.2 圖形結構的物理存儲方式........................................................................................... 104 1.4.2.1 相鄰矩陣.......................................................................................................................... 104 1.4.2.2 圖的鄰接表示 .................................................................................................................. 105 1.4.2.3 圖的多重鄰接表示 .......................................................................................................... 107 1.4.3 圖形結構的遍歷.......................................................................................................... 108 1.4.4 無向連通圖的最小生成樹(minimum-cost spanning tree:MST).............................. 112 1.4.5 有向圖的最短路徑 ...................................................................................................... 114 1.4.5.1 單源最短路徑(single-source shortest paths) ..................................................... 115 1.4.5.2 每對頂點間最短路經(all-pairs shortest paths) ................................................. 117 1.4.6 拓撲排序 ..................................................................................................................... 119
涉及到的內容:數據結構之圖【還能夠的大綱】node
From: https://www.cs.usfca.edu/~galles/visualization/DFS.html算法
struct node{ bool mark; //訪問標誌 char letter; //頂點數據域 struct edge *out; //指向邊表的指針 };
struct edge{ bool mark; //訪問標誌 int no; //頂點編號 struct edge *link; //指向邊表的後繼 };
表節點存儲的不是頂點的序號,而是指向邊(或者說弧)另外一端相鄰頂點的指針。數組
struct node{ bool mark; //訪問標誌 char letter; //頂點數據域 struct node *nextnode; //指向圖頂點集合中下一個元素的指針 struct arc *out; //指向該頂點邊表的指針 };
struct arc{ bool mark; //訪問標誌 struct node *link; //指向該弧(邊)的另外一端頂點的指針 struct arc *nextarc; // 指向與該頂點鏈接的其他弧(邊)的指針 };
看上去特別像倒排表:[IR] Inverted Index & Boolean retrieval網絡
連通:若是從v到w存在一條(無向)路徑,則稱v和w是連通的數據結構
路徑:v到w的路徑是一系列的頂點的集合,其中任一對相鄰的頂點間都有圖中的邊。路徑的長度是路徑中的邊數(若是帶權,則是全部邊的權重和)。若是v和w之間的全部頂點都不一樣,則稱簡單路徑(無迴路)post
迴路:起點等於終點的路徑優化
連通圖:圖中任意兩頂點均連通url
連通份量:無向圖中的極大連通子圖spa
強連通;有向圖中頂點v和w之間存在雙向路徑(既有從v->w又有從w->v,能夠不是同一條),則稱v和w是強連通
弱連通:去掉方向後的v和w是連通的
強連通圖:有向圖中任意兩頂點均強連通
強連通份量:有向圖的極大強連通子圖
不一樣的起點,會致使不一樣的遍歷路徑,也就生成了不一樣的「生成樹」。
廣度優先搜索六層,就是「六度空間」 問題。
既然從不一樣的頂點出發會有不一樣的生成樹,而 n 個頂點的生成樹有 n-1 條邊,那麼,當邊帶權的時候(網絡),如何尋找一個(網絡中)的最小生成樹(即樹中各邊權值之和最小)?
如下內容具體參見:[Optimization] Greedy method
從一個點一點一點向外擴張延伸,進入樹內的點的dist都爲0,往外延伸時是與樹中任意一個結點距離最小
選擇整個樹周邊的「最小的邊」。
每次從剩餘全部邊中取最短的邊,所選邊不能構成迴路
最小堆:查找最小的邊
並查集:要鏈接的倆點不在同一棵樹上。Goto: 超有愛的並查集
並查集的實現,int pre[1000]; 這個數組,記錄了每一個大俠的上級是誰。大俠們從1或者0開始編號(依據題意而定),pre[15]=3就表示15號大俠的上級是3號大俠。
若是一我的的上級就是他本身,那說明他就是掌門人了,查找到此爲止。也有孤家寡人自成一派的,好比歐陽鋒,那麼他的上級就是他本身。每一個人都只認本身的上級。好比胡青牛同窗只知道本身的上級是楊左使。
張無忌是誰?不認識!要想知道本身的掌門是誰,只能一級級查上去。
路徑壓縮,每一個人經過指針在某一處查詢本身門派的頭兒。若是join有門派合併事件,則只修改門派的頭兒便可。
Dijkstra算法和 最小生成樹Prim算法最小生成樹算法很是相似,你們能夠先熟悉下個算法。兩個算法都是基於貪心算法。
雖然Dijkstra算法相對來講比Bellman-Ford 算法更快,可是不適用於有負權值邊的圖,貪心算法決定了它的目光短淺。
而Bellman-Ford 算法從全局考慮,能夠檢測到有負權值的迴路。
Ref: Dijkstra算法(一)之 C語言詳解
核心思路
與S集合中相鄰的點中找到最小的(「邊」+相鄰點的「值」),而後更新倆集合便可。
若是edge存在負數,則會破壞以上這句話背後的原則。
時間複雜度:O(E+V*logV)
基本思想
指定起點s (即從頂點s開始計算)。
S:記錄已求出最短路徑的頂點 (以及相應的最短路徑長度);
U:記錄還未求出最短路徑的頂點 (以及該頂點到起點s的距離);
初始時,S中只有起點s;U中是除s以外的頂點,而且U中頂的路徑是"起點s到該頂點的路徑"。
而後,從U中找出路徑最短的頂點,並將其加入到S中;
接着,更新U中的頂點和頂點對應的路徑。
而後,再從U中找出路徑最短的頂點,並將其加入到S中;
接着,更新U中的頂點和頂點對應的路徑。 ... 重複該操做,直到遍歷完全部頂點。
操做步驟
(1) 初始時,S只包含起點s;U包含除s外的其餘頂點,且U中頂點的距離爲"起點s到該頂點的距離"[例如,U中頂點v的距離爲(s,v)的長度,而後s和v不相鄰,則v的距離爲∞]。
(2) 從U中選出"距離最短的頂點k",並將頂點k加入到S中;同時,從U中移除頂點k。
(3) 更新U中各個頂點到起點s的距離。之因此更新U中頂點的距離,是因爲上一步中肯定了k是求出最短路徑的頂點,從而能夠利用k來更新其它頂點的距離;例如,(s,v)的距離可能大於(s,k)+(k,v)的距離。
(4) 重複步驟(2)和(3),直到遍歷完全部頂點。
Ref: Floyd 算法求多源最短路徑
Floyd算法用來找出每對頂點之間的最短距離,它對圖的要求是,
More details, please check : [Optimization] Dynamic programming
/* 其餘內容,再補充 */
End.