鄰接表實現圖
圖的表示方式有兩種:
- 鄰接矩陣(Adjacency Matrix)
- 鄰接表(Adjacency List)
本文采用類似鄰接表的方式實現圖。
圖的基礎接口
public interface Graph<V, E> {
int verticesSize(); // 頂點數量
int edgesSize(); // 邊的數量
void addVertex(V v); // 添加頂點
void addEdge(V from, V to); // 添加邊
void addEdge(V from, V to, E weight); // 添加帶權值的邊
void removeVertex(V v); // 刪除頂點
void removeEdge(V from, V to); // 刪除邊
}
頂點的定義
private static class Vertex<V, E> {
V value; // 頂點的值
Set<Edge<V, E>> inEdges = new HashSet<>(); // 從這個頂點出去的邊
Set<Edge<V, E>> outEdges = new HashSet<>(); // 到這個頂點的邊
public Vertex(V value) {
this.value = value;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Vertex<?, ?> vertex = (Vertex<?, ?>) o;
return Objects.equals(value, vertex.value);
}
@Override
public int hashCode() {
return Objects.hash(value);
}
}
邊的定義
private static class Edge<V, E> {
Vertex<V, E> fromVertex; // 起始頂點
Vertex<V, E> toVertex; // 結束頂點
E weight; // 權重
public Edge(Vertex<V, E> fromVertex, Vertex<V, E> toVertex, E weight) {
this.fromVertex = fromVertex;
this.toVertex = toVertex;
this.weight = weight;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Edge<?, ?> edge = (Edge<?, ?>) o;
return Objects.equals(fromVertex, edge.fromVertex) && Objects.equals(toVertex, edge.toVertex);
}
@Override
public int hashCode() {
return Objects.hash(fromVertex, toVertex);
}
}
鄰接表的結構
public class ListGraph<V, E> implements Graph<V, E> {
Map<V, Vertex<V, E>> vertices = new HashMap<>(); // 存放所有的頂點
Set<Edge<V, E>> edges = new HashSet<>(); // 存放所有的邊
public int verticesSize() {
return vertices.size();
}
public int edgesSize() {
return edges.size();
}
添加頂點
public void addVertex(V v) {
vertices.putIfAbsent(v, new Vertex<>(v));
}
添加邊
public void addEdge(V from, V to) {
addEdge(from, to, null);
}
public void addEdge(V from, V to, E weight) {
// 先判斷頂點是否存在,不存在則添加
addVertex(from);
addVertex(to);
// 根據值獲取頂點
Vertex<V, E> fromVertex = vertices.get(from);
Vertex<V, E> toVertex = vertices.get(to);
Edge<V, E> edge = new Edge(fromVertex, toVertex, weight);
// 存放邊的結構是set,直接添加會導致如果邊存在就會被替換,不存在則添加
fromVertex.outEdges.add(edge);
toVertex.inEdges.add(edge);
edges.add(edge);
}
刪除邊
public void removeEdge(V from, V to) {
// 根據值獲取頂點
Vertex<V, E> fromVertex = vertices.get(from);
Vertex<V, E> toVertex = vertices.get(to);
// 頂點不存在直接返回
if(null == fromVertex || null == toVertex) {
return;
}
Edge<V, E> edge = new Edge<>(fromVertex, toVertex, null);
if (fromVertex.outEdges.remove(edge)) { // 刪除起點出去集合中的邊
toVertex.inEdges.remove(edge); // 刪除終點進入集合中的邊
edges.remove(edge);
}
}
刪除頂點
public void removeVertex(V v) {
// 根據值獲取頂點
Vertex<V, E> vertex = vertices.get(v);
// 頂點不存在直接返回
if(null == vertex) {
return;
}
// 刪除以v爲起點的終點中的進入集合中的邊
vertex.outEdges.forEach(edge -> {
edge.toVertex.inEdges.remove(new Edge(vertex, edge.toVertex, null));
edges.remove(edge);
});
// 刪除以v爲終點的起點中的出去集合中的邊
vertex.inEdges.forEach(edge -> {
edge.fromVertex.outEdges.remove(new Edge(edge.fromVertex, vertex, null));
edges.remove(edge);
});
vertices.remove(v);
}
更多精彩內容關注本人公衆號:架構師升級之路