20162328蔡文琛 week11 大二
20162328 2017-2018-1 《程序設計與數據結構》第十一周學習總結
教材學習內容總結
在無向圖中,表示邊的頂點對是無序的。
如果圖中的兩個頂點之間有邊鏈接,則稱它們是領接的。
如果無向圖中連接頂點的邊數達到最大,則稱為完全圖。
路徑是圖中連接兩個頂點的邊的序列。
第一個頂點和最後一個頂點相圖且邊不重復的路徑稱為環。
在有向圖中,邊是頂點的有序對。
有向圖中的路徑是連接圖中兩個頂點的有向邊的序列。
圖的每條邊上都有對應的權值的圖稱為帶權圖。
圖的深度優先遍歷與廣度優先遍歷的主要差異在於用棧代替隊列來管理便利的過程。
當且僅當從任意頂點的廣度優先遍歷中得到的頂點數等於圖中所含的頂點數時,圖是連通的。
生成樹是包含圖中所有頂點及圖中部分邊的一棵樹。
生成最小樹是其所含邊的權值小於等於圖的任意其他生成樹的邊的權值之和的生成樹。
深度優先遍歷
1.訪問數組初始化:visited[n] = 0
2.訪問頂點:visited[v] = 1
3.取v的第一個鄰接點w;
4.循環遞歸:
while(w存在)
if(w未被訪問過)
從頂點w出發遞歸執行;
w = v的下一個鄰接點;
廣度優先遍歷
- 初始化隊列:visited[n] = 0
- 訪問頂點:visited[v] = 1
- 頂點v加入隊列
循環:
while(隊列是否為空)
v = 隊列頭元素
w = v的第一個鄰接點
while(w存在)
if(如果w未訪問)
visited[w] = 1;
頂點w加入隊列
w = 頂點v的下一個鄰接點有向圖,無向圖
如果給圖的每條邊規定一個方向,那麽得到的圖稱為有向圖,其邊也稱為有向邊。在有向圖中,與一個節點相關聯的邊有出邊和入邊之分,而與一個有向邊關聯的兩個點也有始點和終點之分。相反,邊沒有方向的圖稱為無向圖。
帶權圖
在處理有關圖的實際問題時,往往有值的存在,比如公裏數,運費,城市,人口數以及電話部數等。一般這個值成為權值,帶權值的圖稱為帶權圖或賦權圖。也稱為網。
最小生成樹算法
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 } } }
20162328蔡文琛 week11 大二