需求:
如何用java代码表示以上的有向带权值的图,实现如下接口:
- 查看顶点数
- 查看边数量
- 新增顶点
- 删除顶点
- 新增边
- 删除边
顶点的定义
/**
* 顶点的定义
*/
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 obj) {
Vertex<V, E> vertex = (Vertex<V, E>) obj;
return Objects.equals(value, vertex.value);
}
@Override
public int hashCode() {
return value == null ? 0 : value.hashCode();
}
}
边的定义
/**
* 边的定义
*/
private static class Edge<V, E> {
/**
* 边的起点
*/
Vertex<V, E> from;
/**
* 边的终点
*/
Vertex<V, E> to;
/**
* 边的权值
*/
E weight;
/**
* 只要两条边的起点和终点相等,就认为这两条边相等
*/
@Override
public boolean equals(Object obj) {
Edge<V, E> edge = (Edge<V, E>) obj;
return from.equals(edge.from) && to.equals(edge.to);
}
@Override
public int hashCode() {
return from.hashCode() * 31 + to.hashCode();
}
}
完整代码
/**
* 图-java实现
*
* @author zhangj
* @date 2020/10/1
*/
public class Graph<V, E> {
/**
* 所有的顶点,一个V对应一个顶点
*/
private Map<V, Vertex<V, E>> vertices = new HashMap<>();
/**
* 所有的边
*/
private Set<Edge<V, E>> edges = new HashSet<>();
/**
* 获取图顶点的数量
*/
public int verticesSize() {
return vertices.size();
}
/**
* 获取图边的数量
*/
public int edgesSize() {
return edges.size();
}
/**
* 新增顶点
*/
public void addVertex(V v) {
//判断顶点是否存在,只有不存在才新增
if (vertices.containsKey(v)) {
return;
}
vertices.put(v, new Vertex<>(v));
}
/**
* 删除顶点
*/
public void removeVertex(V v) {
//先从集合里删除
Vertex<V, E> vertex = vertices.remove(v);
if (vertex == null) {
return;
}
//删除这个顶点出度的边
for (Iterator<Edge<V, E>> iterator = vertex.outEdges.iterator(); iterator.hasNext(); ) {
Edge<V, E> edge = iterator.next();
edge.to.inEdges.remove(edge);
//从vertex.outEdges里删除
iterator.remove();
//从集合里删除
edges.remove(edge);
}
//删除这个顶点入度的边
for (Iterator<Edge<V, E>> iterator = vertex.inEdges.iterator(); iterator.hasNext(); ) {
Edge<V, E> edge = iterator.next();
edge.from.outEdges.remove(edge);
//从vertex.outEdges里删除
iterator.remove();
//从集合里删除
edges.remove(edge);
}
}
/**
* 添加边,不带权值
*/
public void addEdge(V fromV, V toV) {
addEdge(fromV, toV, null);
}
/**
* 添加边,带权值
*/
public void addEdge(V fromV, V toV, E weight) {
//查看起点是否存在,不存在新增
Vertex<V, E> fromVertex = vertices.get(fromV);
if (fromVertex == null) {
//新增一个节点
fromVertex = new Vertex<>(fromV);
vertices.put(fromV, fromVertex);
}
//查看终点是否存在,不存在新增
Vertex<V, E> toVertex = vertices.get(toV);
if (toVertex == null) {
//新增一个节点
toVertex = new Vertex<>(toV);
vertices.put(toV, toVertex);
}
//构造一条边
Edge<V, E> edge = new Edge<>(fromVertex, toVertex);
edge.weight = weight;
//删除边
if (fromVertex.outEdges.remove(edge)) {
toVertex.inEdges.remove(edge);
edges.remove(edge);
}
//新增边
fromVertex.outEdges.add(edge);
toVertex.inEdges.add(edge);
edges.add(edge);
}
/**
* 删除边
*/
public void removeEdge(V formV, V toV) {
//判断起点是否存在,不存在直接退出
Vertex<V, E> fromVertex = vertices.get(formV);
if (fromVertex == null) {
return;
}
//判断终点是否存在,不存在直接退出
Vertex<V, E> toVertex = vertices.get(toV);
if (toVertex == null) {
return;
}
//构造一条边
Edge<V, E> edge = new Edge<>(fromVertex, toVertex);
//删除边
if (fromVertex.outEdges.remove(edge)) {
toVertex.inEdges.remove(edge);
edges.remove(edge);
}
}
/**
* 顶点的定义
*/
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 obj) {
Vertex<V, E> vertex = (Vertex<V, E>) obj;
return Objects.equals(value, vertex.value);
}
@Override
public int hashCode() {
return value == null ? 0 : value.hashCode();
}
@Override
public String toString() {
return value == null ? "null" : value.toString();
}
}
/**
* 边的定义
*/
private static class Edge<V, E> {
/**
* 边的起点
*/
Vertex<V, E> from;
/**
* 边的终点
*/
Vertex<V, E> to;
/**
* 边的权值
*/
E weight;
/**
* 构造函数
*
* @param from 起点
* @param to 终点
*/
public Edge(Vertex<V, E> from, Vertex<V, E> to) {
this.from = from;
this.to = to;
}
/**
* 只要两条边的起点和终点相等,就认为这两条边相等
*/
@Override
public boolean equals(Object obj) {
Edge<V, E> edge = (Edge<V, E>) obj;
return from.equals(edge.from) && to.equals(edge.to);
}
@Override
public int hashCode() {
return from.hashCode() * 31 + to.hashCode();
}
@Override
public String toString() {
return "Edge [from=" + from + ", to=" + to + ", weight=" + weight + "]";
}
}
public void print() {
System.out.println("[顶点]-------------------");
vertices.forEach((V v, Vertex<V, E> vertex) -> {
System.out.println(v);
System.out.println("out-----------");
System.out.println(vertex.outEdges);
System.out.println("in-----------");
System.out.println(vertex.inEdges);
});
System.out.println("[边]-------------------");
edges.forEach((Edge<V, E> edge) -> {
System.out.println(edge);
});
}
}
测试
public static void main(String[] args) {
Graph<String, Integer> graph = new Graph<>();
graph.addEdge("V1", "V0", 9);
graph.addEdge("V1", "V2", 3);
graph.addEdge("V2", "V0", 2);
graph.addEdge("V2", "V3", 5);
graph.addEdge("V3", "V4", 1);
graph.addEdge("V0", "V4", 6);
graph.print();
}
运行结果:
[顶点]-------------------
V0
out-----------
[Edge [from=V0, to=V4, weight=6]]
in-----------
[Edge [from=V1, to=V0, weight=9], Edge [from=V2, to=V0, weight=2]]
V1
out-----------
[Edge [from=V1, to=V2, weight=3], Edge [from=V1, to=V0, weight=9]]
in-----------
[]
V2
out-----------
[Edge [from=V2, to=V3, weight=5], Edge [from=V2, to=V0, weight=2]]
in-----------
[Edge [from=V1, to=V2, weight=3]]
V3
out-----------
[Edge [from=V3, to=V4, weight=1]]
in-----------
[Edge [from=V2, to=V3, weight=5]]
V4
out-----------
[]
in-----------
[Edge [from=V3, to=V4, weight=1], Edge [from=V0, to=V4, weight=6]]
[边]-------------------
Edge [from=V1, to=V2, weight=3]
Edge [from=V2, to=V3, weight=5]
Edge [from=V3, to=V4, weight=1]
Edge [from=V0, to=V4, weight=6]
Edge [from=V1, to=V0, weight=9]
Edge [from=V2, to=V0, weight=2]