圖是由頂點集(VertexSet)和邊集(EdgeSet)組成,針對圖G,頂點集和邊集分別記爲V(G)和E(G)。java
依據圖的邊集是否爲有向,可把圖分爲有向圖和無向圖node
根據圖是否有權重,能夠分爲有權圖和無權圖。算法
public interface Graph { boolean insertEdge(int v1,int v2,int weight); boolean deleteEdge(int v1,int v2); int getDegree(int v); int getInDegree(int v); int getOutDegree(int v); String depthFirstSearch(int v); String breathFirstSearch(int v); GraphType getGraphType(); int getFirstNeighbor(int v); // none return -1 int getNextNeighbor(int v,int v2); // none return -1 int getSize(); int getWeight(int v1,int v2); int getEdgeSize(); }
圖的基本知識
圖的概念
圖是由頂點集(VertexSet)和邊集(EdgeSet)組成,針對圖G,頂點集和邊集分別記爲V(G)和E(G)。數組
依據圖的邊集是否爲有向,可把圖分爲有向圖和無向圖緩存
根據圖是否有權重,能夠分爲有權圖和無權圖。數據結構
圖的基本術語:app
-
鄰接點:在一個無向圖中,若存在一條邊(Vi,Vj),則稱Vi,Vj爲此邊的兩個端點,並稱它們互爲鄰接點ide
-
出/入邊:在一個有向圖張,若存在一條邊<Vi,Vj>,則稱此邊爲頂點Vi的出邊,頂點Vj的一條入邊;函數
-
度/入度/出度:無向圖中的度定義爲以該頂點爲一個端點的邊的數目,記爲D(V)。有向圖的入度定義爲多少邊指向該頂點,出度是該頂點出邊的個數;this
注意:這裏不考慮自環和多重邊
圖的表示方式
圖的表示方式有兩種:
- 二維數組表示(鄰接矩陣)
- 鏈表表示(鄰接表)
(1)鄰接矩陣表示(Adjacency Matrix)
在無向圖中,鄰接矩陣是對稱的;
在無權圖中,用0表示邊<i,j>是不鏈接的,用1表示邊<i,j>是鏈接的;
在有權圖中,用INF表示邊<i,j>是不鏈接的,用weight表示邊<i,j>是鏈接的;
圖的類型 | 示例 |
---|---|
無向無權圖 | |
有向無權圖 | |
有向有權圖 |
(2)鄰接表表示(Linked-adjacency Lists)
鄰接矩陣與鄰接表相比,它會形成空間的必定損失,它須要爲每一個頂點都分配n個邊的空間,其實有不少邊都是不存在邊,可是鄰接表的實現就不同,它只關心存在的邊,不關心不存在的邊。鄰接表由數組+鏈表組成對於上面的無向圖,鄰接表表示爲(因爲有向和無向的差異不是太大,因此只是畫出了無向的鄰接表表示):
圖 | 鄰接表 |
---|---|
注:若要表示有權圖,將鄰接表的節點數據結構中增長一個weight數據便可
圖的JAVA實現
本程序只實現了基本功能,即節點表示爲1,2,..,n,暫不支持泛型與刪節點
圖的類型
圖有四種類型
- 有向有權圖
- 無向有權圖
- 有向無權圖
- 無向無權圖
public enum GraphType { DirectionWeight, NoDirectionWeight, DirectionNoWeight, NoDirectionNoWeight; }
圖的接口類
定義一個圖的接口類,以下:
public interface Graph { boolean insertEdge(int v1,int v2,int weight); boolean deleteEdge(int v1,int v2); int getDegree(int v); int getInDegree(int v); int getOutDegree(int v); String depthFirstSearch(int v); String breathFirstSearch(int v); GraphType getGraphType(); int getFirstNeighbor(int v); // none return -1 int getNextNeighbor(int v,int v2); // none return -1 int getSize(); int getWeight(int v1,int v2); int getEdgeSize(); }
本程序只實現了基本功能,即節點表示爲1,2,..,n,暫不支持泛型與刪節點
具體實現
(1)LinkGraph類與MatrixGraph類
顧名思義,用鄰接表與鄰接矩陣實現圖。
實現了Graph接口,成員變量與構造函數以下:
public class LinkGraph implements Graph { private LinkedList<VertexNode>[] vexList; private int edgeSize; // 已有邊數 private GraphType type; private int maxVertex; // 頂點最大個數 private static final int INF = 999999; // 用於有權圖的無邊表示 Iterator<VertexNode> temp; // 用於緩存getNeighbor方法的Iterator public LinkGraph(GraphType type, int size) { vexList = new LinkedList[size + 1]; for (int i = 1; i < size + 1; i++) { vexList[i] = new LinkedList(); } maxVertex = size; edgeSize = 0; this.type = type; } private class VertexNode { // 鄰接表節點的內部類 int vertex; int weight; VertexNode(int vex, int weight) { vertex = vex; this.weight = weight; } VertexNode(int vex) { vertex = vex; this.weight = 1; } }
public class MatrixGraph implements Graph { private int[][] matrix; private int edgeSize; // 已有邊數 private GraphType type; private int maxVertex; // 頂點最大個數 private static final int INF = 999999; // 用於有權圖的無邊表示 public MatrixGraph(GraphType type, int size) { matrix = new int[size + 1][size + 1]; maxVertex = size; edgeSize = 0; this.type = type; switch (type) { case DirectionWeight: case NoDirectionWeight: for (int i = 0; i < size + 1; i++) { for (int j = 0; j < size + 1; j++) { matrix[i][j] = INF; } } break; case DirectionNoWeight: case NoDirectionNoWeight: for (int i = 0; i < size + 1; i++) { for (int j = 0; j < size + 1; j++) { matrix[i][j] = 0; } } break; } }
注意用鄰接矩陣實現時,由於圖的類型不一樣致使的表示不一樣,常須要先判斷,後進行操做。
(2)insertEdge方法與deleteEdge方法
boolean insertEdge(int v1,int v2,int weight); boolean deleteEdge(int v1,int v2);
這裏須要注意的地方是加邊和刪邊的時候要修改edgeSize變量,因此須要一些判斷語句
在無權圖中,不管weight爲多少咱們都把他看成1
鄰接表實現
@Override public boolean insertEdge(int v1, int v2, int weight) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } boolean contain = false; switch (type) { case DirectionNoWeight: weight = 1; case DirectionWeight: for (VertexNode vex : vexList[v1]) { if (vex.vertex == v2) contain = true; } if (!contain) edgeSize++; vexList[v1].add(new VertexNode(v2, weight)); break; case NoDirectionNoWeight: weight = 1; case NoDirectionWeight: for (VertexNode vex : vexList[v1]) { if (vex.vertex == v2) contain = true; } if (!contain) edgeSize++; vexList[v1].add(new VertexNode(v2, weight)); vexList[v2].add(new VertexNode(v1, weight)); break; } return true; } @Override public boolean deleteEdge(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } Iterator<VertexNode> iterator; switch (type) { case DirectionNoWeight: case DirectionWeight: iterator = vexList[v1].listIterator(0); while (iterator.hasNext()) { if (iterator.next().vertex == v2) { iterator.remove(); edgeSize--; break; } } break; case NoDirectionWeight: case NoDirectionNoWeight: iterator = vexList[v1].listIterator(0); while (iterator.hasNext()) { if (iterator.next().vertex == v2) { iterator.remove(); edgeSize--; iterator = vexList[v2].listIterator(0); while (iterator.hasNext()) { if (iterator.next().vertex == v1) { iterator.remove(); edgeSize--; break; } break; } } break; } } return true; }
值得注意的是鄰接表實現中咱們加入的是內部類(VertexNode)做爲節點,所以在遍歷的時候用到了鏈表的Iterator
鄰接矩陣實現
@Override public boolean insertEdge(int v1, int v2, int weight) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } switch (type) { case DirectionNoWeight: if (matrix[v1][v2] == 0) edgeSize++; matrix[v1][v2] = 1; break; case NoDirectionNoWeight: if (matrix[v1][v2] == 0) edgeSize++; matrix[v1][v2] = 1; matrix[v2][v1] = 1; break; case DirectionWeight: if (matrix[v1][v2] == INF) edgeSize++; matrix[v1][v2] = weight; break; case NoDirectionWeight: if (matrix[v1][v2] == INF) edgeSize++; matrix[v1][v2] = weight; matrix[v2][v1] = weight; break; } return true; } @Override public boolean deleteEdge(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } switch (type) { case DirectionNoWeight: if (matrix[v1][v2] != 0) edgeSize--; matrix[v1][v2] = 0; break; case NoDirectionNoWeight: if (matrix[v1][v2] != 0) edgeSize--; matrix[v1][v2] = 0; matrix[v2][v1] = 0; break; case DirectionWeight: if (matrix[v1][v2] != INF) edgeSize--; matrix[v1][v2] = INF; break; case NoDirectionWeight: if (matrix[v1][v2] != INF) edgeSize--; matrix[v1][v2] = INF; matrix[v2][v1] = INF; break; } return true; }
(3)getDegree系列方法
int getDegree(int v); int getInDegree(int v); int getOutDegree(int v);
分別爲獲取v節點的度、入度、出度的方法。
第一個方法有一個統一的實現
public int getDegree(int v) { if (type == GraphType.NoDirectionWeight || type == GraphType.NoDirectionNoWeight) return getOutDegree(v); // 由於算起來比GetInDegree快 else return getInDegree(v) + getOutDegree(v); }
鄰接表實現
鄰接表沒有什麼難度,也無需分類,直接遍歷
@Override public int getInDegree(int v) { int count = 0; for (int i = 1; i < maxVertex+1; i++) { if(i==v) continue; Iterator<VertexNode> iterator = vexList[i].listIterator(0); while (iterator.hasNext()){ if(iterator.next().vertex==v){ count++; break; } } } return count; } @Override public int getOutDegree(int v) { return vexList[v].size(); }
鄰接矩陣實現
公式如上,只須要遍歷鄰接矩陣便可。
@Override public int getInDegree(int v) { int degree = 0; switch (type) { case DirectionWeight: case NoDirectionWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[i][v] != INF) degree++; } break; case DirectionNoWeight: case NoDirectionNoWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[i][v] != 0) degree++; } break; } return degree; } @Override public int getOutDegree(int v) { int degree = 0; switch (type) { case DirectionWeight: case NoDirectionWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != INF) degree++; } break; case DirectionNoWeight: case NoDirectionNoWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != 0) degree++; } break; } return degree; }
(4)getNeighbor系列方法
int getFirstNeighbor(int v); // none return -1 int getNextNeighbor(int v,int v2); // none return -1
這兩個方法是用來實現後面的算法的,實現起來也很簡單
鄰接表實現
@Override public int getFirstNeighbor(int v) { if(vexList[v].size()!=0){ return vexList[v].getFirst().vertex; }else return -1; } @Override public int getNextNeighbor(int v, int v2) { Iterator<VertexNode> iterator = vexList[v].listIterator(); while (iterator.hasNext()){ if(iterator.next().vertex==v2) if(iterator.hasNext()) return iterator.next().vertex; else return -1; } return -1; }
鄰接矩陣實現
@Override public int getFirstNeighbor(int v) { if (type == GraphType.NoDirectionNoWeight || type == GraphType.DirectionNoWeight) { for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != 0 && i != v) { return i; } } } else { for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != INF && i != v) { return i; } } } return -1; } @Override public int getNextNeighbor(int v, int v2) { if (type == GraphType.NoDirectionNoWeight || type == GraphType.DirectionNoWeight) { for (int i = v2 + 1; i < maxVertex + 1; i++) { if (matrix[v][i] != 0 && i != v) { return i; } } } else { for (int i = v2 + 1; i < maxVertex + 1; i++) { if (matrix[v][i] != INF && i != v) { return i; } } } return -1; }
(5)getWeight方法
這個方法主要是用來做爲後續算法的接口,爲了把圖類作封裝。
通常來說只有有權圖的時候纔會用到這個方法,定義若是不存在邊的話返回INF。
鄰接表實現
@Override public int getWeight(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return INF; } Iterator<VertexNode> iterator = vexList[v1].listIterator(); while (iterator.hasNext()) { VertexNode node = iterator.next(); if (node.vertex == v2) return node.weight; } return INF; }
鄰接矩陣實現
@Override public int getWeight(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return INF; } return matrix[v1][v2]; }
(6)深度優先搜索(DFS)
-
思想:
從圖中某個頂點V0出發,訪問它,而後選擇一個V0鄰接到的未被訪問的一個鄰接點V1出發深度優先遍歷圖,當遇到一個全部鄰接於它的結點都被訪問過了的結點U時,回退到前一次剛被訪問過的擁有未被訪問的鄰接點W,再從W出發深度遍歷......直到連通圖中的全部頂點都被訪問過爲止。
實現過程須要new一個boolean數組,標記節點是否訪問過
鄰接表和鄰接矩陣的實現方式一致
@Override public String depthFirstSearch(int v) { boolean[] visited = new boolean[maxVertex + 1]; StringBuffer rs = new StringBuffer(); rs.append(v + " → "); DFS(v, visited, rs); return rs.toString(); } private void DFS(int v, boolean[] visited, StringBuffer rs) { visited[v] = true; int next = getFirstNeighbor(v); while (next != -1) { if (!visited[next]) { rs.append(next + " → "); DFS(next, visited, rs); } next = getNextNeighbor(v, next); } }
(7)廣度優先搜索(BFS)
-
思想
從圖中某頂點V0出發,在訪問了V0以後依次訪問v0的各個不曾訪問過的鄰接點,而後分別從這些鄰接點出發廣度優先遍歷圖,直至圖中全部頂點都被訪問到爲止
實現過程須要new一個boolean數組,標記節點是否訪問過
使用到了隊列結構
鄰接表和鄰接矩陣的實現方式一致
@Override public String breathFirstSearch(int v) { StringBuffer rs = new StringBuffer(); boolean[] visited = new boolean[maxVertex+1]; rs.append(v + " → "); visited[v]=true; Queue<Integer> queue = new LinkedList<>(); queue.offer(v); while (!queue.isEmpty()){ v = queue.poll(); int next = getFirstNeighbor(v); while (next!=-1) { if (!visited[next]) { rs.append(next + " → "); visited[next] = true; queue.offer(next); } next = getNextNeighbor(v,next); } } return rs.toString(); }
完整代碼
LinkGraph
import java.util.Iterator; import java.util.LinkedList; import java.util.Queue; public class LinkGraph implements Graph { private LinkedList<VertexNode>[] vexList; private int edgeSize; private GraphType type; private int maxVertex; private static final int INF = 999999; // 用於有權圖的無邊表示 Iterator<VertexNode> temp; // 用於緩存getNeighbor方法的Iterator public LinkGraph(GraphType type, int size) { vexList = new LinkedList[size + 1]; for (int i = 1; i < size + 1; i++) { vexList[i] = new LinkedList(); } maxVertex = size; edgeSize = 0; this.type = type; } @Override public boolean insertEdge(int v1, int v2, int weight) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } boolean contain = false; switch (type) { case DirectionNoWeight: weight = 1; case DirectionWeight: for (VertexNode vex : vexList[v1]) { if (vex.vertex == v2) contain = true; } if (!contain) edgeSize++; vexList[v1].add(new VertexNode(v2, weight)); break; case NoDirectionNoWeight: weight = 1; case NoDirectionWeight: for (VertexNode vex : vexList[v1]) { if (vex.vertex == v2) contain = true; } if (!contain) edgeSize++; vexList[v1].add(new VertexNode(v2, weight)); vexList[v2].add(new VertexNode(v1, weight)); break; } return true; } @Override public boolean deleteEdge(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } Iterator<VertexNode> iterator; switch (type) { case DirectionNoWeight: case DirectionWeight: iterator = vexList[v1].listIterator(0); while (iterator.hasNext()) { if (iterator.next().vertex == v2) { iterator.remove(); edgeSize--; break; } } break; case NoDirectionWeight: case NoDirectionNoWeight: iterator = vexList[v1].listIterator(0); while (iterator.hasNext()) { if (iterator.next().vertex == v2) { iterator.remove(); edgeSize--; iterator = vexList[v2].listIterator(0); while (iterator.hasNext()) { if (iterator.next().vertex == v1) { iterator.remove(); edgeSize--; break; } break; } } break; } } return true; } @Override public int getDegree(int v) { if (type == GraphType.NoDirectionWeight || type == GraphType.NoDirectionNoWeight) return getOutDegree(v); // 由於算起來比GetInDegree快 else return getInDegree(v) + getOutDegree(v); } @Override public int getInDegree(int v) { int count = 0; for (int i = 1; i < maxVertex+1; i++) { if(i==v) continue; Iterator<VertexNode> iterator = vexList[i].listIterator(0); while (iterator.hasNext()){ if(iterator.next().vertex==v){ count++; break; } } } return count; } @Override public int getOutDegree(int v) { return vexList[v].size(); } @Override public String depthFirstSearch(int v) { boolean[] visited = new boolean[maxVertex + 1]; StringBuffer rs = new StringBuffer(); rs.append(v + " → "); DFS(v, visited, rs); return rs.toString(); } private void DFS(int v, boolean[] visited, StringBuffer rs) { visited[v] = true; int next = getFirstNeighbor(v); while (next != -1) { if (!visited[next]) { rs.append(next + " → "); DFS(next, visited, rs); } next = getNextNeighbor(v, next); } } @Override public String breathFirstSearch(int v) { StringBuffer rs = new StringBuffer(); boolean[] visited = new boolean[maxVertex+1]; rs.append(v + " → "); visited[v]=true; Queue<Integer> queue = new LinkedList<>(); queue.offer(v); while (!queue.isEmpty()){ v = queue.poll(); int next = getFirstNeighbor(v); while (next!=-1) { if (!visited[next]) { rs.append(next + " → "); visited[next] = true; queue.offer(next); } next = getNextNeighbor(v,next); } } return rs.toString(); } @Override public GraphType getGraphType() { return type; } @Override public int getFirstNeighbor(int v) { if(vexList[v].size()!=0){ return vexList[v].getFirst().vertex; }else return -1; } @Override public int getNextNeighbor(int v, int v2) { Iterator<VertexNode> iterator = vexList[v].listIterator(); while (iterator.hasNext()){ if(iterator.next().vertex==v2) if(iterator.hasNext()) return iterator.next().vertex; else return -1; } return -1; } @Override public int getSize() { return maxVertex; } @Override public int getWeight(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return INF; } Iterator<VertexNode> iterator = vexList[v1].listIterator(); while (iterator.hasNext()) { VertexNode node = iterator.next(); if (node.vertex == v2) return node.weight; } return INF; } private class VertexNode { int vertex; int weight; VertexNode(int vex, int weight) { vertex = vex; this.weight = weight; } VertexNode(int vex) { vertex = vex; this.weight = 1; } } @Override public int getEdgeSize() { return edgeSize; } }
MatrixGraph
import java.util.LinkedList; import java.util.Queue; public class MatrixGraph implements Graph { public static void main(String[] args) { Graph graph = new MatrixGraph(GraphType.DirectionWeight, 10); graph.insertEdge(1, 3, 1); graph.insertEdge(4, 3, 1); graph.insertEdge(3, 8, 1); graph.insertEdge(6, 3, 1); graph.insertEdge(8, 9, 1); System.out.println(graph.getInDegree(7)); System.out.println(graph.getOutDegree(3)); System.out.println(graph.getDegree(3)); } private int[][] matrix; private int edgeSize; private GraphType type; private int maxVertex; private static final int INF = 999999; // 用於有權圖的無邊表示 public MatrixGraph(GraphType type, int size) { matrix = new int[size + 1][size + 1]; maxVertex = size; edgeSize = 0; this.type = type; switch (type) { case DirectionWeight: case NoDirectionWeight: for (int i = 0; i < size + 1; i++) { for (int j = 0; j < size + 1; j++) { matrix[i][j] = INF; } } break; case DirectionNoWeight: case NoDirectionNoWeight: for (int i = 0; i < size + 1; i++) { for (int j = 0; j < size + 1; j++) { matrix[i][j] = 0; } } break; } } @Override public boolean insertEdge(int v1, int v2, int weight) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } switch (type) { case DirectionNoWeight: if (matrix[v1][v2] == 0) edgeSize++; matrix[v1][v2] = 1; break; case NoDirectionNoWeight: if (matrix[v1][v2] == 0) edgeSize++; matrix[v1][v2] = 1; matrix[v2][v1] = 1; break; case DirectionWeight: if (matrix[v1][v2] == INF) edgeSize++; matrix[v1][v2] = weight; break; case NoDirectionWeight: if (matrix[v1][v2] == INF) edgeSize++; matrix[v1][v2] = weight; matrix[v2][v1] = weight; break; } return true; } @Override public boolean deleteEdge(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return false; } switch (type) { case DirectionNoWeight: if (matrix[v1][v2] != 0) edgeSize--; matrix[v1][v2] = 0; break; case NoDirectionNoWeight: if (matrix[v1][v2] != 0) edgeSize--; matrix[v1][v2] = 0; matrix[v2][v1] = 0; break; case DirectionWeight: if (matrix[v1][v2] != INF) edgeSize--; matrix[v1][v2] = INF; break; case NoDirectionWeight: if (matrix[v1][v2] != INF) edgeSize--; matrix[v1][v2] = INF; matrix[v2][v1] = INF; break; } return true; } @Override public int getDegree(int v1) { if (type == GraphType.NoDirectionWeight || type == GraphType.NoDirectionNoWeight) return getInDegree(v1); else return getInDegree(v1) + getOutDegree(v1); } @Override public int getInDegree(int v) { int degree = 0; switch (type) { case DirectionWeight: case NoDirectionWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[i][v] != INF) degree++; } break; case DirectionNoWeight: case NoDirectionNoWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[i][v] != 0) degree++; } break; } return degree; } @Override public int getOutDegree(int v) { int degree = 0; switch (type) { case DirectionWeight: case NoDirectionWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != INF) degree++; } break; case DirectionNoWeight: case NoDirectionNoWeight: for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != 0) degree++; } break; } return degree; } @Override public String depthFirstSearch(int v) { boolean[] visited = new boolean[maxVertex + 1]; StringBuffer rs = new StringBuffer(); rs.append(v + " → "); DFS(v, visited, rs); return rs.toString(); } private void DFS(int v, boolean[] visited, StringBuffer rs) { visited[v] = true; int next = getFirstNeighbor(v); while (next != -1) { if (!visited[next]) { rs.append(next + " → "); DFS(next, visited, rs); } next = getNextNeighbor(v, next); } } @Override public String breathFirstSearch(int v) { StringBuffer rs = new StringBuffer(); boolean[] visited = new boolean[maxVertex+1]; rs.append(v + " → "); visited[v]=true; Queue<Integer> queue = new LinkedList<>(); queue.offer(v); while (!queue.isEmpty()){ v = queue.poll(); int next = getFirstNeighbor(v); while (next!=-1) { if (!visited[next]) { rs.append(next + " → "); visited[next] = true; queue.offer(next); } next = getNextNeighbor(v,next); } } return rs.toString(); } @Override public GraphType getGraphType() { return type; } @Override public int getFirstNeighbor(int v) { if (type == GraphType.NoDirectionNoWeight || type == GraphType.DirectionNoWeight) { for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != 0 && i != v) { return i; } } } else { for (int i = 1; i < maxVertex + 1; i++) { if (matrix[v][i] != INF && i != v) { return i; } } } return -1; } @Override public int getNextNeighbor(int v, int v2) { if (type == GraphType.NoDirectionNoWeight || type == GraphType.DirectionNoWeight) { for (int i = v2 + 1; i < maxVertex + 1; i++) { if (matrix[v][i] != 0 && i != v) { return i; } } } else { for (int i = v2 + 1; i < maxVertex + 1; i++) { if (matrix[v][i] != INF && i != v) { return i; } } } return -1; } @Override public int getSize() { return maxVertex; } @Override public int getWeight(int v1, int v2) { if (v1 < 1 || v1 > maxVertex || v2 < 1 || v2 > maxVertex) { System.out.println("無效輸入,退出"); return INF; } return matrix[v1][v2]; } @Override public int getEdgeSize() { return edgeSize; } }