20162328 2017-2018-1 《程序設計與數據結構》第十週學習總結算法
理解圖與有向圖、無向圖
理解帶權圖
會應用帶權圖
理解圖的廣度優先遍歷和深度優先遍歷
掌握最小生成樹算法
掌握圖的實現數組
若是給圖的每條邊規定一個方向,那麼獲得的圖稱爲有向圖,其邊也稱爲有向邊。在有向圖中,與一個節點相關聯的邊有出邊和入邊之分,而與一個有向邊關聯的兩個點也有始點和終點之分。相反,邊沒有方向的圖稱爲無向圖。
數據結構
在處理有關圖的實際問題時,每每有值的存在,好比千米數,運費,城市,人口數以及電話部數等。通常這個值成爲權值,帶權值的圖稱爲帶權圖或賦權圖。也稱爲網。學習
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 } } }