常見的非線性結構有兩種——樹和圖,在通過了三週對樹的學習以後,本週咱們接觸了另外一種非線性結構圖的相關內容,包括圖的概念、圖的分類、圖的實現方法等。html
protected final int DEFAULT_CAPACITY = 5; protected int numVertices; // 頂點數目 protected boolean[][] adjMatrix; // 布爾值的矩陣,存儲頂點之間有無邊 protected T[] vertices; // 存儲頂點及頂點的value protected int modCount; public Graph() { numVertices = 0; this.adjMatrix = new boolean[DEFAULT_CAPACITY][DEFAULT_CAPACITY]; this.vertices = (T[])(new Object[DEFAULT_CAPACITY]); }
addEdge方法
:此方法用於在頂點之間添加邊,添加的方法有兩種,一種方法要輸入的參數是兩個頂點,另外一種方法要輸入的參數是兩個頂點在鄰接矩陣中的索引值。public void addEdge(int index1, int index2) { if (indexIsValid(index1) && indexIsValid(index2)) { adjMatrix[index1][index2] = true; adjMatrix[index2][index1] = true; modCount++; } } // 使用頂點進行添加的方法實質上和上面用索引值添加的方法是同樣的,只不過它使用了一個getIndex方法來獲取頂點的索引值 public void addEdge(T vertex1, T vertex2) { addEdge(getIndex(vertex1), getIndex(vertex2)); } // getIndex方法經過遍歷存放頂點的泛型數組找到頂點的索引值,頂點在泛型數組中的索引值即爲它在鄰接矩陣中的索引值 public int getIndex(T vertex) { for (int i = 0;i < numVertices;i++){ if (vertices[i] == vertex){ return i; } else{ return -1; } } return -1; }
addVertex方法
:此方法用於向圖中添加新的頂點,添加過程當中有兩個步驟,一是在泛型數組中添加該頂點,二是在鄰接矩陣中增長一行和一列,並把其中全部恰當的位置都設爲false。public void addVertex(T vertex) { //當鄰接矩陣滿了的時候,對其進行擴容 if ((numVertices + 1) == adjMatrix.length) { expandCapacity(); } //步驟一:在泛型數組中添加該頂點 vertices[numVertices] = vertex; //步驟二:把鄰接矩陣中的適當位置改成false for (int i = 0; i < numVertices; i++) { adjMatrix[numVertices][i] = false; adjMatrix[i][numVertices] = false; } numVertices++; modCount++; }
expandCapacity方法
:用鄰接矩陣實現無向圖中的擴容與其餘用數組實現的擴容方法不一樣,它不只要複製數組,還要對鄰接矩陣進行復制和擴容。protected void expandCapacity() { // 建立新的泛型數組和鄰接矩陣 T[] largerVertices = (T[])(new Object[vertices.length*2]); boolean[][] largerAdjMatrix = new boolean[vertices.length*2][vertices.length*2]; // 外層循環進行泛型數組的複製,同時協助內層循環進行鄰接矩陣的複製 for (int i = 0; i < numVertices; i++) { // 內層循環進行鄰接矩陣的複製 for (int j = 0; j < numVertices; j++) { largerAdjMatrix[i][j] = adjMatrix[i][j]; } largerVertices[i] = vertices[i]; } // 將擴容後的兩者賦值給原來的泛型數組和鄰接矩陣 vertices = largerVertices; adjMatrix = largerAdjMatrix; }
private ArrayList<VerticeNode> vertices; // 用於存儲頂點 private int numVertices; // 記錄頂點的個數 private int modCount; public LinearGraph(){ numVertices = 0; modCount = 0; a = 0; vertices = new ArrayList<VerticeNode>(); }
@Override public void addVertex(Object vertex) { VerticeNode node = new VerticeNode(vertex); vertices.add(node); modCount++; numVertices++; }
@Override public void removeVertex(Object vertex) { int i = 0; // 將目標頂點刪除 while (vertices.get(i).getElement() != vertex){ i++; } vertices.remove(i); // 將頂點以後的列表裏的元素前移 for (int j = 0;j < numVertices;j++){ VerticeNode temp = vertices.get(j); while (temp.getNext() != null){ if (temp.getNext().getElement() == vertex){ temp.setNext(temp.getNext().getNext()); } temp = temp.getNext(); } break; } modCount--; numVertices--; }
@Override public void addEdge(Object vertex1, Object vertex2) { // 尋找頂點要被添加的位置 int i = 0; while (vertices.get(i).getElement() != vertex1){ i++; } // 在頂點一的鏈表末端添加頂點二,在兩頂點之間創建邊 VerticeNode temp = vertices.get(i); while (temp.getNext() != null){ temp = temp.getNext(); } temp.setNext(new VerticeNode(vertex2)); // 對頂點二的鏈表進行上述相同操做 int j = 0; while (vertices.get(j).getElement() != vertex2){ j++; } VerticeNode temp1 = vertices.get(j); while (temp1.getNext() != null){ temp1 = temp1.getNext(); } temp1.setNext(new VerticeNode(vertex1)); }
@Override public void removeEdge(Object vertex1, Object vertex2) { // 找到所要刪除的頂點的位置 int i = 0; while (vertices.get(i).getElement() != vertex1){ i++; } // 在頂點一的鏈表中找到頂點二的前驅結點 VerticeNode temp = vertices.get(i); while (temp.getNext().getElement() != vertex2){ temp = temp.getNext(); } // 若是頂點二位於末端,直接將temp的next設爲空便可 if (temp.getNext().getNext() == null){ temp.setNext(null); } // 若是頂點二位於中間,將temp的next設置爲頂點二的next便可 else { temp.getNext().setNext(temp.getNext().getNext()); } }
VerticeNode
類,直接進行添加就能夠了。上週沒有測試。java
代碼行數(新增/累積) | 博客量(新增/累積) | 學習時間(新增/累積) | 重要成長 | |
---|---|---|---|---|
目標 | 5000行 | 30篇 | 400小時 | |
第一週 | 10/10 | 1/1 | 10/10 | |
第二週 | 246/366 | 2/3 | 20/30 | |
第三週 | 567/903 | 1/4 | 10/40 | |
第四周 | 2346/3294 | 2/6 | 20/60 | |
第五週 | 2346/3294 | 2/8 | 30/90 | |
第六週 | 1343/4637 | 2/8 | 20/110 | |
第七週 | 654/5291 | 1/9 | 25/135 | |
第八週 | 2967/8258 | 1/10 | 15/150 | |
第九周 | 2871/11129 | 2/12 | 20/170 |