数据结构与算法之图的基本实现

2020-04-29  本文已影响0人  Peakmain

图的分类

有向图
有明确方向的图

image.png image.png

无向图

混合图
可能是有向,也可能是无向

image.png

简单图和多重图

性质2推导:比如4个顶点


image.png

首先6连边的结果:一共3条边


image.png
然后8连边的结果:一共2条,最后3连边一共1条结果
image.png

所以边数一共是:3+2+1=4*3/2=n(n-1)/2

图的实现方案

图有两种常见的实现方案
1、领接矩阵
2、领接表

邻接矩阵的存储方式
一维数组存放顶点信息
二维数组存放边信息

image.png

v1->v0有边所以写1,v0->v1没有边,所有写0

弊端:我们会发现画的红色斜线,上下对称,所以领接矩阵比较浪费内存

领接表

图的基础接口定义

public interface Graph<V, E> {
    /**
     * 边得大小
     */
    int edgesSize();

    /**
     * 顶点的大小
     */
    int verticesSize();

    /**
     * 添加顶点
     * @param v 顶点
     */
    void addVertext(V v);

    /**
     * 添加边
     * @param from 入度顶点
     * @param to 出度顶点
     */
    void addEdge(V from, V to);
    /**
     * 添加边
     * @param from 入度顶点
     * @param to 出度顶点
     * @param weight 权重
     */
    void addEdge(V from, V to, E weight);

    /**
     * 移除顶点
     * @param v 顶点
     */
    void removeVertex(V v);

    /**
     * 移除边
     * @param from 入度顶点
     * @param to 出度顶点
     */
    void removeEdge(V from, V to);
}

图的基础实现

image.png

顶点的定义

    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 v) {
            this.value = v;
        }
        @Override
        public boolean equals(Object obj) {
            return Objects.equals(value, ((Vertex<V, E>)obj).value);
        }
        @Override
        public int hashCode() {
            return value == null ? 0 : value.hashCode();
        }
        @Override
        public String toString() {
            return value == null ? "" : value.toString();
        }
    }

边的定义

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

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

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

        @Override
        public int hashCode() {
            return 31 * from.hashCode() + to.hashCode();
        }

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

添加顶点

   private Map<V, Vertex<V, E>> vertices = new HashMap<>();
    @Override
    public int verticesSize() {
        return vertices.size();
    }
    /**
     * 添加顶点
     */
    @Override
    public void addVertext(V v) {
        if (vertices.containsKey(v)) return;
        vertices.put(v, new Vertex<>(v));
    }

添加边

    private Set<Edge<V, E>> edges = new HashSet<>();
    @Override
    public int edgesSize() {
        return edges.size();
    }
    /**
     * 添加边
     * @param from 入度顶点
     * @param to 出度顶点
     */
    @Override
    public void addEdge(V from, V to) {
        addEdge(from, to, null);
    }

    /**
     * 添加边
     * @param from 入度顶点
     * @param to 出度顶点
     * @param weight 权重
     */
    @Override
    public void addEdge(V from, V to, E weight) {
        Vertex<V, E> fromVertex = vertices.get(from);
        if (fromVertex == null) {
            fromVertex = new Vertex<>(from);
            vertices.put(from, fromVertex);
        }
        Vertex<V, E> toVertex = vertices.get(to);
        if (toVertex == null) {
            toVertex = new Vertex<>(to);
            vertices.put(to, 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);
    }

删除某边

image.png
    @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);
        }
    }

删除某个顶点

image.png
    @Override
    public void removeVertex(V v) {
        Vertex<V, E> vertex = vertices.remove(v);
        if (vertex == null) return;
        //出度 1->2->3 移除2
        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);
        }
    }

测试

打印工具类封装

  public void print() {
        vertices.forEach((V v, Vertex<V, E> vertex) -> {
            System.out.print("\t\t\t|-----");
            System.out.print("入度:");
            System.out.print(vertex.inEdges);
            System.out.println("\t\t\t|");
            System.out.print("\t\t\t|");
            System.out.print("\n[顶点]:");
            System.out.println(v +"--->");
            System.out.println("\t\t\t|");
            System.out.println("\t\t\t|");
            System.out.print("\t\t\t|-----");
            System.out.print("出度:");
            System.out.println(vertex.outEdges);

            System.out.println("\n\n");
        });

        System.out.println("-----------[边]-----------");
        edges.forEach((Edge<V, E> edge) -> {
            System.out.println(edge);
        });
    }

main函数中有向图

        ListGraph<String, Integer> graph = new ListGraph<>();
        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.addEdge("V1", "V0", 12);
        graph.print();
部分截图.png

移除v2->v0这条边

graph.removeEdge("V2","V0");
image.png

移除顶点

        graph.removeVertex("V2");
image.png image.png

无向图

        ListGraph<String, Integer> graph = new ListGraph<>();
        graph.addEdge("V0", "V1");
        graph.addEdge("V1", "V0");

        graph.addEdge("V0", "V2");
        graph.addEdge("V2", "V0");

        graph.addEdge("V0", "V3");
        graph.addEdge("V3", "V0");

        graph.addEdge("V1", "V2");
        graph.addEdge("V2", "V1");

        graph.addEdge("V2", "V3");
        graph.addEdge("V3", "V2");

        graph.print();
上一篇下一篇

猜你喜欢

热点阅读