20162328 2017-2018-1 《程序設計與數據結構》第十一週學習總結算法
在無向圖中,表示邊的頂點對是無序的。
若是圖中的兩個頂點之間有邊連接,則稱它們是領接的。
若是無向圖中鏈接頂點的邊數達到最大,則稱爲徹底圖。
路徑是圖中鏈接兩個頂點的邊的序列。
第一個頂點和最後一個頂點相圖且邊不重複的路徑稱爲環。
在有向圖中,邊是頂點的有序對。
有向圖中的路徑是鏈接圖中兩個頂點的有向邊的序列。
圖的每條邊上都有對應的權值的圖稱爲帶權圖。
圖的深度優先遍歷與廣度優先遍歷的主要差別在於用棧代替隊列來管理便利的過程。
當且僅當從任意頂點的廣度優先遍歷中獲得的頂點數等於圖中所含的頂點數時,圖是連通的。
生成樹是包含圖中全部頂點及圖中部分邊的一棵樹。
生成最小樹是其所含邊的權值小於等於圖的任意其餘生成樹的邊的權值之和的生成樹。數組
1.訪問數組初始化:visited[n] = 0
2.訪問頂點:visited[v] = 1
3.取v的第一個鄰接點w;
4.循環遞歸:
while(w存在)
if(w未被訪問過)
從頂點w出發遞歸執行;
w = v的下一個鄰接點;數據結構
循環:
while(隊列是否爲空)
v = 隊列頭元素
w = v的第一個鄰接點
while(w存在)
if(若是w未訪問)
visited[w] = 1;
頂點w加入隊列
w = 頂點v的下一個鄰接點學習
若是給圖的每條邊規定一個方向,那麼獲得的圖稱爲有向圖,其邊也稱爲有向邊。在有向圖中,與一個節點相關聯的邊有出邊和入邊之分,而與一個有向邊關聯的兩個點也有始點和終點之分。相反,邊沒有方向的圖稱爲無向圖。設計
在處理有關圖的實際問題時,每每有值的存在,好比千米數,運費,城市,人口數以及電話部數等。通常這個值成爲權值,帶權值的圖稱爲帶權圖或賦權圖。也稱爲網。code
public class WeightedGraph { private final int MAX_VERTS = 20; //最大頂點數 private final int INFINITY = 100000; //最遠距離...表示沒法達到 private Vertex[] vertexArray; //存儲頂點的數組 private int adjMat[][]; //存儲頂點之間的邊界 private int nVerts; //頂點數量 private int currentVert; //當前頂點索引 private PriorityQ thePQ; //存儲邊的優先級隊列 private int nTree; //最小生成樹中的頂點數量 public WeightedGraph() { vertexArray = new Vertex[MAX_VERTS]; adjMat = new int[MAX_VERTS][MAX_VERTS]; for(int i = 0; i < MAX_VERTS; i++) { for(int j = 0; j < MAX_VERTS; j++) { adjMat[i][j] = INFINITY; //初始化全部邊界無窮遠 } } thePQ = new PriorityQ(); } public void addVertex(char lab) { //添加頂點 vertexArray[nVerts++] = new Vertex(lab); } public void addEdge(int start, int end, int weight) {//添加帶權邊 adjMat[start][end] = weight; adjMat[end][start] = weight; } public void displayVertex(int v) { System.out.print(vertexArray[v].label); } /* * 帶權圖的最小生成樹,要選擇一條最優的路徑 */ public void MinSpanningTree() { currentVert = 0; //從0開始 while(nTree < nVerts-1) { //當不是全部節點都在最小生成樹中時 //isInTree是上一節Vertex類中新添加的成員變量 private boolean isInTree; //表示有沒有加入到樹中,初始化爲false vertexArray[currentVert].isInTree = true; //將當前頂點加到樹中 nTree++; //往PQ中插入與當前頂點相鄰的一些邊界 for(int i = 0; i < nVerts; i++) { if(i == currentVert) //若是是本頂點,跳出 continue; if(vertexArray[i].isInTree) //若是頂點i已經在樹中,跳出 continue; int distance = adjMat[currentVert][i]; //計算當前頂點到i頂點的距離 if(distance == INFINITY) continue; //若是當前頂點與i頂點無窮遠,跳出 putInPQ(i, distance); //將i節點加入PQ中 } if(thePQ.size() == 0) { //若是PQ爲空,表示圖不鏈接 System.out.println("Graph not connected!"); return; } Edge theEdge = thePQ.removeMin(); int sourceVert = theEdge.srcVert; currentVert = theEdge.destVert; System.out.print(vertexArray[sourceVert].label);//這裏就是一步步打印最小生成樹的路徑 System.out.print(vertexArray[currentVert].label); System.out.print(" "); } } //這個方法是將一個Edge放入優先級隊列,保證隊列中每一個Edge的des頂點是不一樣的。 private void putInPQ(int newVert, int newDist) { int queueIndex = thePQ.find(newVert);//判斷PQ中是否已經有到相同目的頂點的邊界 if(queueIndex != -1) { //若是有則與當前頂點到目的頂點的距離做比較,保留短的那個 Edge tempEdge = thePQ.peekN(queueIndex);//get edge int oldDist = tempEdge.distance; if(oldDist > newDist) { //若是新的邊界更短 thePQ.removeN(queueIndex); //刪除舊邊界 Edge theEdge = new Edge(currentVert, newVert, newDist); thePQ.insert(theEdge); } } else { //若是PQ中沒有到相同目的頂點的邊界 Edge theEdge = new Edge(currentVert, newVert, newDist); thePQ.insert(theEdge);//直接添加到PQ } } }