java使用鄰接表實現圖

鄰接表實現圖

圖的表示方式有兩種:

  • 鄰接矩陣(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);
}

更多精彩內容關注本人公衆號:架構師升級之路
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章