區別 | 聯繫 | |
---|---|---|
徹底 | 任意兩個頂點之間都會有一條邊 | |
連通 | 任意兩個頂點之間都存在一條路徑 | 徹底的必定連通 |
補充知識:偏序:有向圖中兩個頂點之間不存在環路,至於連通與否,是無所謂的。全序:就是在偏序的基礎之上,有向無環圖中的任意一對頂點還須要有明確的關係(反映在圖中,就是單向連通的關係,注意不能雙向連通,那就成環了)。html
問題3:廣度優先遍歷的代碼理解。java
public Iterator<T> iteratorBFS(int startIndex) { Integer x; QueueADT<Integer> traversalQueue = new LinkedQueue<Integer>(); UnorderedListADT<T> resultList = new ArrayUnorderedList<T>(); if (!indexIsValid(startIndex)) return resultList.iterator(); boolean[] visited = new boolean[numVertices]; for (int i = 0; i < numVertices; i++) visited[i] = false; traversalQueue.enqueue(new Integer(startIndex)); visited[startIndex] = true; while (!traversalQueue.isEmpty()) { x = traversalQueue.dequeue(); resultList.addToRear(vertices[x.intValue()]); for (int i = 0; i < numVertices; i++) { if (adjMatrix[x.intValue()][i] && !visited[i]) { traversalQueue.enqueue(new Integer(i)); visited[i] = true; } } } return new GraphIterator(resultList.iterator()); }
//先把全部的頂點都標記成未訪問的。 for (int i = 0; i < numVertices; i++) visited[i] = false;
//把其實頂點入隊,標記爲已訪問。 traversalQueue.enqueue(new Integer(startIndex)); visited[startIndex] = true;
//當隊不爲空的時候,x等於隊首元素 while (!traversalQueue.isEmpty()) { x = traversalQueue.dequeue(); //intValue()以 int 類型返回該 Integer 的值。把頂點對應的值放入無序列表中。 resultList.addToRear(vertices[x.intValue()]); //小於頂點數作一個循環,鄰接矩陣的出的那個元素 for (int i = 0; i < numVertices; i++) { //若是頂點到i存在邊而且i沒有被標記,則i入隊,i被標記。 if (adjMatrix[x.intValue()][i] && !visited[i]) { traversalQueue.enqueue(new Integer(i)); visited[i] = true; } } } return new GraphIterator(resultList.iterator());
resultGraph.adjMatrix[i][j]=Double.POSITIVE_INFINITY
是什麼意思?問題1:git
問題1解決方案:改爲下圖就好,由於進行的是頂點的元素進行比較,而不是結點進行比較。算法
//增長頂點 public void addVertex(T vertex) { //越界擴容 if ((numVertices + 1) == adjMatrix.length) expandCapacity(); //把新加頂點到剩下全部頂點的路徑定義爲正無窮(鄰接矩陣) vertices[numVertices] = vertex; for (int i = 0; i <= numVertices; i++) { adjMatrix[numVertices][i] = Double.POSITIVE_INFINITY; adjMatrix[i][numVertices] = Double.POSITIVE_INFINITY; } numVertices++; modCount++; }
//刪除頂點 public void removeVertex(T vertex) { removeVertex(getIndex(vertex)); } //根據索引去找到該頂點 public void removeVertex(int index) { //當索引值存在時 if (indexIsValid(index)) { //從該頂點開始,頂點集中的每一個數的位置須要向前移一位 for (int j = index; j < numVertices - 1; j++) { vertices[j] = vertices[j + 1]; } //數組中的最後一個位置定義爲空 vertices[numVertices - 1] = null; //從該頂點開始,邊的起點從該頂點變爲下一個頂點,由於頂點集的位置向前移了一位。 for (int i = index; i < numVertices - 1; i++) { for (int x = 0; x < numVertices; x++) adjMatrix[i][x] = adjMatrix[i + 1][x]; } //由於無向圖,因此從該頂點開始,邊的終點從該頂點變爲下一個頂點依次類推 for (int i = index; i < numVertices; i++) { for (int x = 0; x < numVertices; x++) adjMatrix[x][i] = adjMatrix[x][i + 1]; } //數組中最後一個位置爲空,到各個頂點的邊爲空 for (int i = 0; i < numVertices; i++) { adjMatrix[numVertices][i] = Double.POSITIVE_INFINITY; adjMatrix[i][numVertices] = Double.POSITIVE_INFINITY; } //個數-1,操做次數+1 numVertices--; modCount++; } }
//輸入頂點添加邊 public void addEdge(T vertex1, T vertex2, double weight) { //根據頂點的索引值添加邊 addEdge(getIndex(vertex1), getIndex(vertex2), weight); } public void addEdge(int index1, int index2, double weight) { //當起點終點的索引值都存在的時候,由於是無向圖,因此權重都相同,鄰接矩陣相應的位置放入權重。操做次數+1 if (indexIsValid(index1) && indexIsValid(index2)) { adjMatrix[index1][index2] = weight; adjMatrix[index2][index1] = weight; modCount++; } }
//刪除邊 public void removeEdge(T vertex1, T vertex2) { //根據頂點的索引值刪除邊 removeEdge(getIndex(vertex1), getIndex(vertex2)); } public void removeEdge(int index1, int index2) { //當起點終點的索引值都存在的時候 if (indexIsValid(index1) && indexIsValid(index2)) { //把邊上的權重都變爲正無窮大 adjMatrix[index1][index2] = Double.POSITIVE_INFINITY; adjMatrix[index2][index1] = Double.POSITIVE_INFINITY; modCount++; } }
//找到兩個頂點間的最短路徑 public int shortestPathLength(T startVertex, T targetVertex) { //根據索引值找到最短路徑長度 return shortestPathLength(getIndex(startVertex), getIndex(targetVertex)); } private int shortestPathLength(int startIndex, int targetIndex) { int result = 0; //若是起始索引值或者終止索引值不存在時,返回0 if (!indexIsValid(startIndex) || !indexIsValid(targetIndex)) return 0; int index1; //找到起點到終點最小路徑的頂點的索引值 Iterator<Integer> it = iteratorShortestPathIndices(startIndex, targetIndex); //若是沒有下一個則爲0,沒路徑 if (it.hasNext()) index1 = ((Integer) it.next()).intValue(); else return 0; //有下一個則+1,做爲長度 while (it.hasNext()) { result++; it.next(); } return result; }
//輸出最小路徑中的頂點 public Iterator iteratorShortestPath(T startVertex, T targetVertex) { return iteratorShortestPath(getIndex(startVertex), getIndex(targetVertex)); } public Iterator iteratorShortestPath(int startIndex, int targetIndex) { List<T> resultList = new ArrayList<T>(); if (!indexIsValid(startIndex) || !indexIsValid(targetIndex)) return resultList.iterator(); //獲得最小路徑中的頂點索引值 Iterator<Integer> it = iteratorShortestPathIndices(startIndex, targetIndex); //把對應的頂點添加到列表裏 while (it.hasNext()) resultList.add(vertices[((Integer) it.next()).intValue()]); return new GraphIterator(resultList.iterator()); }
protected Iterator<Integer> iteratorShortestPathIndices(int startIndex, int targetIndex) { int index = startIndex; int[] pathLength = new int[numVertices];/*存路徑的長度*/ int[] predecessor = new int[numVertices];/*前驅頂點*/ QueueADT<Integer> traversalQueue = new LinkedQueue<Integer>();/*索引值*/ UnorderedListADT<Integer> resultList = new ArrayUnorderedList<Integer>();/*頂點元素*/ /*若是索引值不存在或者起始終止索引值相等,返回無序列表中的頂點元素*/ if (!indexIsValid(startIndex) || !indexIsValid(targetIndex) || (startIndex == targetIndex)) return resultList.iterator(); /*作標記,先把標記數組所有變爲false*/ boolean[] visited = new boolean[numVertices]; for (int i = 0; i < numVertices; i++) visited[i] = false; /*把起始索引值加入列表*/ traversalQueue.enqueue(Integer.valueOf(startIndex)); /*對該索引值進行標記*/ visited[startIndex] = true; /*該長度數組中該索引值的位置定位爲0,前驅結點定義爲-1*/ pathLength[startIndex] = 0; predecessor[startIndex] = -1; /*當索引值列表不爲空而且起始和終止頂點元素不一樣時*/ while (!traversalQueue.isEmpty() && (index != targetIndex)) { //index = 出隊列的元素(也就是以前存入的索引值) index = (traversalQueue.dequeue()).intValue(); //找出該索引值到每一個頂點的邊 for (int i = 0; i < numVertices; i++) { //若是邊存在,而且終點未標記(也就是這個邊沒有找到過) if (adjMatrix[index][i] < Double.POSITIVE_INFINITY && !visited[i]) { /*把邊的終點的索引值對應的長度數組+1*/ pathLength[i] = pathLength[index] + 1; /*前驅結點終點的索引值對應的位置存入index*/ predecessor[i] = index; /*把新的索引值加入隊列*/ traversalQueue.enqueue(Integer.valueOf(i)); /*標記該頂點*/ visited[i] = true; } } } if (index != targetIndex) // no path must have been found return resultList.iterator(); StackADT<Integer> stack = new LinkedStack<Integer>(); index = targetIndex; //找到最小路徑中的頂點索引值,進行入棧 stack.push(Integer.valueOf(index)); do { index = predecessor[index]; stack.push(Integer.valueOf(index)); } while (index != startIndex); //依次彈棧獲得正確的順序 while (!stack.isEmpty()) resultList.addToRear((stack.pop())); return new NetworkIndexIterator(resultList.iterator()); }
//找到最便宜的路 public double shortestPathWeight(T vertex1, T vertex2) { return shortestPathWeight(getIndex(vertex1), getIndex(vertex2)); } public double shortestPathWeight(int start, int end) { Double[] dist = new Double[numVertices];//存放該頂點對全部有邊頂點的權重 boolean[] flag = new boolean[numVertices];//標記結點 for (int i = 0; i < numVertices; i++) { flag[i] = false;/*讓全部都變成未標記*/ dist[i] = adjMatrix[start][i];/*初始等於該頂點到全部頂點的權重(包括不存在邊的爲正無窮)*/ } flag[start] = true;/*把開始頂點標記*/ int k = 0; for (int i = 0; i < numVertices; i++) { Double min = Double.POSITIVE_INFINITY; for (int j = 0; j < numVertices; j++) { //若是爲標記,而且該索引值下存在權重(也就是存在邊) if (flag[j] == false && dist[j] < min && dist[j] != -1 && dist[j] != 0) { min = dist[j];/*最小值就爲該權重*/ k = j;/*讓k等於該索引值*/ } } flag[k] = true;/*標記該索引值的頂點*/ /*找k索引值的剩下權重是否存在,若是有找到最小的添加到min裏,若是沒有一直+0*/ for (int j = 0; j < numVertices; j++) { if (adjMatrix[k][j] != -1&&dist[j]!= -1) { double temp = (adjMatrix[k][j] == Double.POSITIVE_INFINITY ? Double.POSITIVE_INFINITY : (min + adjMatrix[k][j])); //若是j未標記而且temp小於權重組中原有值,則讓權重組j爲索引的位置爲temp if (flag[j] == false && (temp < dist[j])) { dist[j] = temp; } } } } return dist[end]; }
24540數組
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 0/0 | 1/1 | 2/2 | |
第二週 | 1010/1010 | 1/2 | 10/12 | |
第三週 | 651/1661 | 1/3 | 13/25 | |
第四周 | 2205/3866 | 1/4 | 15/40 | |
第五週 | 967/4833 | 2/6 | 22/62 | |
第六週 | 1680/6513 | 1/7 | 34/96 | |
第七週 | 2196/8709 | 1/8 | 35/131 | |
第八週 | 1952/10661 | 2/9 | 49/180 | |
第九周 | 2100/24540 | 1/10 | 40/131 |
計劃學習時間:30小時網絡
實際學習時間:40小時數據結構
改進狀況:圖的概念很好理解,可是實現很難!學習