publicAdjMatrix(String filename){ File file = new File(filename); Scanner scanner = null; try { scanner = new Scanner(file); // 如果读取到的 V 和 E 小于 0,那么抛出异常 this.V = scanner.nextInt(); if (this.V < 0) { thrownew IllegalArgumentException("V Must Be Positive"); } matrix = newint[this.V][this.V]; this.E = scanner.nextInt(); if (this.E < 0) { thrownew IllegalArgumentException("E Must Be Positive"); }
for (int i = 0; i < this.E; i++) { // 对读取到的顶点编号进行验证,是否在 [0, V) 的范围中 int a = scanner.nextInt(); validateVertex(a); int b = scanner.nextInt(); validateVertex(b);
// 对顶点编号进行验证,是否合法 privatevoidvalidateVertex(int v){ if (v < 0 || v >= this.V) { thrownew IllegalArgumentException("Vertex " + v + " is invalid"); } }
// 返回顶点数 publicintV(){ returnthis.V; }
// 返回边数 publicintE(){ returnthis.E; }
// 返回与顶点 v 相邻的所有顶点 public ArrayList<Integer> adj(int v){ validateVertex(v); ArrayList<Integer> res = new ArrayList<>(); for (int i = 0; i < this.V; i++) { if (this.matrix[v][i] == 1) { res.add(i); } }
return res; }
// 判断顶点 v 和 w 是否相邻 publicbooleanhasEdge(int v, int w){ validateVertex(v); validateVertex(w); returnthis.matrix[v][w] == 1; }
// 返回顶点 v 的度,即与顶点 v 相邻的顶点的个数 publicintdegree(int v){ return adj(v).size(); }
publicAdjList(String filename){ File file = new File(filename); Scanner scanner = null; try { scanner = new Scanner(file); this.V = scanner.nextInt(); if (this.V < 0) { thrownew IllegalArgumentException("V Must Be Positive"); }
// 初始化链表 this.lists = new LinkedList[this.V]; for (int i = 0; i < this.V; i++) { this.lists[i] = new LinkedList<>(); }
this.E = scanner.nextInt(); if (this.E < 0) { thrownew IllegalArgumentException("E Must Be Positive"); }
for (int i = 0; i < this.E; i++) { int a = scanner.nextInt(); validateVertex(a); int b = scanner.nextInt(); validateVertex(b);
if (a == b) { thrownew IllegalArgumentException("Self loop exists"); } // 平行边的判断 if (lists[a].contains(b)) { thrownew IllegalArgumentException("Parallel edge exists"); }
publicAdjSet(String filename){ File file = new File(filename); Scanner scanner = null; try { scanner = new Scanner(file); this.V = scanner.nextInt(); if (this.V < 0) { thrownew IllegalArgumentException("V Must Be Positive"); }
// 初始化链表 this.sets = new TreeSet[this.V]; for (int i = 0; i < this.V; i++) { this.sets[i] = new TreeSet<>(); }
this.E = scanner.nextInt(); if (this.E < 0) { thrownew IllegalArgumentException("E Must Be Positive"); }
for (int i = 0; i < this.E; i++) { int a = scanner.nextInt(); validateVertex(a); int b = scanner.nextInt(); validateVertex(b);
if (a == b) { thrownew IllegalArgumentException("Self loop exists"); } // 平行边的判断 if (sets[a].contains(b)) { thrownew IllegalArgumentException("Parallel edge exists"); }
privatevoidvalidateVertex(int v){ if (v < 0 || v >= this.V) { thrownew IllegalArgumentException("Vertex " + v + " is invalid"); } }
publicintV(){ returnthis.V; }
publicintE(){ returnthis.E; }
public TreeSet<Integer> adj(int v){ validateVertex(v);
// 直接返回自己的链表即可 return sets[v]; }
publicbooleanhasEdge(int v, int w){ validateVertex(v); validateVertex(w); returnthis.sets[v].contains(w); }
publicintdegree(int v){ return adj(v).size(); }
@Override public String toString(){ StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(String.format("V: %d, E: %d\n", this.V, this.E)); for (int v = 0; v < this.V; v++) { stringBuilder.append(String.format("%d : ", v)); for (int w: adj(v)) { stringBuilder.append(String.format("%d ", w)); } stringBuilder.append("\n"); } return stringBuilder.toString(); }
publicstaticvoidmain(String[] args){ AdjSet adjSet = new AdjSet("g.txt"); System.out.println(adjSet); } }
在最后我们做一个改进,观察三个类的 adj 方法
// AdjMatrix public ArrayList<Integer> adj(int v){ validateVertex(v); ArrayList<Integer> res = new ArrayList<>(); for (int i = 0; i < this.V; i++) { if (this.matrix[v][i] == 1) { res.add(i); } }
return res; }
// AdjList public LinkedList<Integer> adj(int v){ validateVertex(v); return lists[v]; }
// AdjSet public TreeSet<Integer> adj(int v){ validateVertex(v); return sets[v]; }