* Graph.java
package com.merrytech;
import java.util.HashMap;
import java.util.Map;
import java.util.LinkedList;
import java.util.Set;
public class Graph<E> {
private final int v; // number of vertices
private int e; // number of edges
private final HashMap<E, LinkedList<E>> adj; // adjacency lists
public Graph(int v) {
this.v = v;
this.e = 0;
this.adj = new HashMap<>(v);
}
public int countV() { return this.v; }
public int countE() { return this.e; }
public void addEdge(E v, E w) {
this.adj.computeIfAbsent(v, k -> new LinkedList<>());
this.adj.computeIfAbsent(w, k -> new LinkedList<>());
this.adj.get(v).add(w);
this.adj.get(w).add(v);
this.e += 1;
}
public LinkedList<E> getAdjList(E v) {
return this.adj.get(v);
}
public Set<E> getVertices() {
return this.adj.keySet();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(this.v).append(" vertices, ").append(this.e).append(" edges\n");
for (Map.Entry<E, LinkedList<E>> entry : this.adj.entrySet()) {
sb.append(entry.getKey().toString()).append(": ");
for (E w : entry.getValue()) {
sb.append(w.toString()).append(" ");
}
sb.append("\n");
}
return sb.toString();
}
public int degree(E v) {
int degree = 0;
for (E w : this.getAdjList(v)) {
degree += 1;
}
return degree;
}
public int maxDegree() {
int max = 0;
int thisDegree = 0;
for (E v : this.getVertices()) {
thisDegree = this.degree(v);
if (thisDegree > max) {
max = thisDegree;
}
}
return max;
}
public double avgDegree() {
return 2.0 * this.countE() / this.countV();
}
public int numberOfSelfLoops() {
int count = 0;
for (E v : this.getVertices()) {
for (E w : this.getAdjList(v)) {
// System.out.printf("v=%s,w=%s\n", v, w);
if (v.equals(w)) {
count += 1;
}
}
}
return count / 2;
}
}
* Main.java
package com.merrytech;
public class Main {
public static void main(String[] args) {
// write your code here
Graph<String> graph = new Graph<>(7);
graph.addEdge("A", "B");
graph.addEdge("A", "C");
graph.addEdge("A", "F");
graph.addEdge("A", "G");
graph.addEdge("D", "E");
graph.addEdge("D", "F");
graph.addEdge("E", "F");
graph.addEdge("E", "G");
// self loops edges
graph.addEdge("A", "A");
graph.addEdge("E", "E");
System.out.println(graph.toString());
System.out.printf("Degree of vertex E: %d\n", graph.degree("E")); // 3
System.out.printf("Degree of vertex A: %d\n", graph.degree("A")); // 4
System.out.printf("count self-loops=%d\n", graph.numberOfSelfLoops()); // 2
System.out.printf("Max degree=%d\n", graph.maxDegree()); // 4
System.out.printf("Average degree=%.3f\n", graph.avgDegree());
}
}
JDK 1.8
领接表 LinkedList换成HashSet, 就不会有重复的边。
深度优先 DFS
* DepthFirstSearch.java
package com.merrytech;
import java.util.HashMap;
public class DepthFirstSearch<K> {
private HashMap<K, Boolean> marked;
private int count;
public DepthFirstSearch(Graph<K> g, K s, Handler<K> h) {
this.count = 0;
this.marked = new HashMap<>();
this.dfs(g, s, h);
}
private void dfs(Graph<K> g, K v, Handler<K> h) {
this.marked.put(v, true);
count += 1;
for (K w : g.getAdjList(v)) {
if (!this.marked.containsKey(w)) {
this.dfs(g, w, h);
}
}
h.visit(v);
}
public boolean marked(K w) { return this.marked.containsKey(w); }
public int count() {return this.count;}
}
* Handler.java
package com.merrytech;
public class Handler<E> {
public Handler() {}
public void visit(E e) {
System.out.print(e + " ");
}
}
* Main.java
改写主类
package com.merrytech;
public class Main {
public static void main(String[] args) {
Graph<Integer> graph = new Graph<>(6);
graph.addEdge(0, 2);
graph.addEdge(0, 1);
graph.addEdge(1, 2);
graph.addEdge(3, 5);
graph.addEdge(3, 4);
graph.addEdge(3, 2);
graph.addEdge(2, 4);
graph.addEdge(5, 0);
System.out.println(graph.toString());
new DepthFirstSearch<>(graph, 0, new Handler<>());
System.out.println();
}
}
marked[] TreeMap Key需要传Comparable, 比较Key大小关系,用HashMap算了。
adj[] 用HashSet自动从小到大排序,为了与示例测试数据一致,用LinkedList