图(Graph)的实现

图

如果所示,一幅图包含了若干个顶点和若干条边,每条边含有权重。
废话不说,下面讲讲如何实现一幅图吧
由图可知,一幅图由两部分组成,顶点和边,而边依赖于顶点,每条边包含了两个顶点和权重,由此可得到,每个顶点可抽象出一个类,每条边可抽象一个类。

顶点:

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 String toString() {
            return value == null ? "null" : value.toString();
        }

        @Override
        public boolean equals(Object o) {
            Vertex<?, ?> vertex = (Vertex<?, ?>) o;
            return Objects.equals(value, vertex.value);
        }

        @Override
        public int hashCode() {
            return Objects.hash(value);
        }
    }

边:

static class Edge<V, E>{
        Vertex<V, E> from;
        Vertex<V, E> to;
        E weight;

        @Override
        public String toString() {
            return "Edge{" +
                    "from=" + from.toString() +
                    ", to=" + to.toString() +
                    ", weight=" + weight +
                    '}';
        }

        public Edge(Vertex<V, E> from, Vertex<V, E> to) {
            this.from = from;
            this.to = to;
        }

        public Edge(Vertex<V, E> from, Vertex<V, E> to, E weight) {
            this.from = from;
            this.to = to;
            this.weight = weight;
        }

        @Override
        public boolean equals(Object o) {
            Edge<?, ?> edge = (Edge<?, ?>) o;
            return Objects.equals(from, edge.from) && Objects.equals(to, edge.to);
        }

        @Override
        public int hashCode() {
            return Objects.hash(from, to);
        }

每个图会有CRUD,所以暂时定义几个接口:

    int edgesSize();//获取边的数量
    int verticesSize(); //获取顶点的数量

    void addVertex(V value); //添加顶点

    void addEdge(V from, V to);//添加边

    void addEdge(V from, V to, E weight); //添加边和权重

    void removeVertex(V v); //删除顶点

    void removeEdge(V from, V to); //删除边

    void print(); //打印图的信息

实现:定义类实现这几个方法,实现类中包含这两个属性,

//key:顶点的值 value:顶点
private final Map<V, Vertex<V, E>> vertices = new HashMap<>();
//边的信息
private final Set<Edge<V, E>> edges = new HashSet<>();

打印图的信息:

@Override
public void print() {
    System.out.println("---------------------------------------------------------------------");
    vertices.forEach((k, v) -> {
        System.out.print(k);
        System.out.println("  in: " + v.inEdges);
        System.out.println("    out: " + v.outEdges);
    });
    edges.forEach(System.out::println);
    System.out.println("---------------------------------------------------------------------");
}

添加顶点:

只需要往图的顶点集合中添加就行

@Override
public void addVertex(V value) {
    vertices.computeIfAbsent(value, k -> new Vertex<>(value));
}

添加边(无权重):

@Override
public void addEdge(V from, V to) {
    addEdge(from, to, null);
}

添加边:

先看看顶点是否存在,存在就拿出来,不存在就新添加顶点。

将这条边加入到以该fromVertex为起点的边的集合中

将这条边加入到以该toVertex为终点的边的集合中

@Override
public void addEdge(V from, V to, E weight) {
    Vertex<V, E> fromVertex = vertices.computeIfAbsent(from, k -> new Vertex<>(from));
    Vertex<V, E> toVertex = vertices.computeIfAbsent(to, k -> new Vertex<>(to));
    Edge<V, E> edge = new Edge<>(fromVertex, toVertex, weight);
    if (fromVertex.outEdges.remove(edge)) {
        toVertex.inEdges.remove(edge);
        edges.remove(edge);
    }
    fromVertex.outEdges.add(edge);
    toVertex.inEdges.add(edge);
    edges.add(edge);
}

删除顶点:

通过当前 顶点获取到连接到该顶点的所有边,根据该边获取到另一个端点,将该边从另一个端点的集合中删除即可

@Override
public void removeVertex(V v) {
    Vertex<V, E> vertex = vertices.remove(v);
    if (vertex != null) {
        Iterator<Edge<V, E>> outIterator = vertex.outEdges.iterator();
        while (outIterator.hasNext()) {
            Edge<V, E> edge = outIterator.next();
            edge.to.inEdges.remove(edge);
            outIterator.remove();
            edges.remove(edge);
        }
        Iterator<Edge<V, E>> inIterator = vertex.inEdges.iterator();
        while (inIterator.hasNext()) {
            Edge<V, E> edge = inIterator.next();
            edge.from.outEdges.remove(edge);
            inIterator.remove();
            edges.remove(edge);
        }
    }
}

删除边:

删除一条边,思路:找到这条边对应的两个顶点,对于起点来说,将这条边从以这个顶点为起点的边的集合中删除即可;对于这条的终点,将这条边从以这个顶点为终点的边的集合中删除即可。

@Override
public void removeEdge(V from, V to) {
    Vertex<V, E> fromVertex = vertices.get(from);
    if (fromVertex == null) {
        return;
    }
    Vertex<V, E> toVertex = vertices.get(to);
    if (toVertex == null) {
        return;
    }
    Edge<V, E> edge = new Edge<>(fromVertex, toVertex);
    if (fromVertex.outEdges.remove(edge)) {
        toVertex.inEdges.remove(edge);
        edges.remove(edge);
    }
}

获取顶点的数量:

@Override
public int verticesSize() {
    return vertices.size();
}

获取边的数量:

@Override
public int edgesSize() {
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值