图建模

  为了方便的使用图这个数据结构,我们需要使用编程语言对其抽象的内容进行具体化,我们在设计一个复杂的数据结构的时候可以参考Java集合框架的特点,首先定义一个接口,包含的是图的所有的常用的公共的操作,然后定义一个抽象类来部分地实现这个接口,最后根据具体的使用情况定义具体的类实现抽象类。

  图的常用操作:

    1、获取图中顶点个数

    2、获取图中的顶点

    3、返回指定顶点下标的顶点对象

    4、返回指定顶点的下标

    5、返回指定下标的顶点的邻居

    6、打印边

    7、清除图

    8、添加顶点

    9、添加边

通过接口,将这些图的常用操作定义封装在一起:

import java.util.List;

/**
 *
 * @param <V> 参数V是一个泛型,表示图中顶点
 *
 */
public interface Graph<V> {
    /**
     *
     * @return 返回值是图中的顶点个数
     */
    public int getSize();

    /**
     *
     * @return 返回值是图中所有的顶点对象
     */
    public List<V> getVertices();

    /**
     *
     * @param index 表示要获取的顶点的索引
     * @return 返回指定下标的顶点对象
     */
    public V getVertex(int index);

    /**
     *
     * @param v 参数v表示要获取下标的顶点对象
     * @return 返回值是指定下标的顶点的索引
     */

    public int getIndex(V v);

    /**
     *
     * @param index
     * @return  返回指定下标的顶点的邻居
     */

    public List<Integer> getNeighbors(int index);

    /**
     *
     * @param v
     * @return  返回指定顶点的度
     */
    public int getDegree(int v);

    /**
     * 打印所有的边
     */

    public void printEdges();

    /**
     * 清楚图
     */
    public void clear();

    /**
     * 向图中添加顶点vertex
     * @param vertex
     */
    public boolean addVertex(V vertex);

    /**
     * 向图中添加边<u,v>
     * @param u
     * @param v
     */
    public boolean addEdge(int u,int v);
}

  定义一个抽象类,部分实现了上面的接口,其实已经实现了接口中所有的方法,但是为了以后方便的在接口中增加新的方法,而这个方法不需要当前这个抽象类来实现,所以将这个类定义为抽象类,方便维护接口和类。

import java.util.ArrayList;
import java.util.List;

public abstract class AbstractGraph<V> implements Graph<V> {

    List<V> vertices = new ArrayList<>();
    List<List<Edge>> neighbors = new ArrayList<>();

    public AbstractGraph() {
    }

    /**
     * 由一个顶点数组和边数组构建一个图
     * @param vertices
     * @param edges
     */
    public AbstractGraph(V[] vertices,int[][] edges ) {

        for (V vertex : vertices) {
            addVertex(vertex);
        }
        createAdjacencyLists(edges);
    }

    protected  void createAdjacencyLists(int[][] edges){

        for (int i = 0; i < edges.length; i++) {

            addEdge(edges[i][0],edges[i][1]);
        }
    }

    /**
     * 由一个顶点列表和一个边列表构建图
     * @param edges
     */
    public AbstractGraph(List<V> vertices,List<Edge> edges) {

        for (V vertex : vertices) {
            addVertex(vertex);
        }
        createAdjacencyLists(edges);
    }

    protected  void createAdjacencyLists(List<Edge> edges){

        for (Edge edge : edges) {
            addEdge(edge.getU(),edge.getV());
        }
    }

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

    @Override
    public List getVertices() {
        return vertices;
    }

    @Override
    public V getVertex(int index) {
        return vertices.get(index);
    }

    @Override
    public int getIndex(V v) {
        return vertices.indexOf(v);
    }

    @Override
    public List<Integer> getNeighbors(int index) {

        ArrayList<Integer> res = new ArrayList<>();

        for (Edge edge : neighbors.get(index)) {
            res.add(edge.getV());
        }
        return res;
    }

    @Override
    public int getDegree(int v) {
        return neighbors.get(v).size();
    }

    @Override
    public void printEdges() {

        for (int i = 0; i < neighbors.size(); i++) {

            System.out.println(getVertex(i) + "(" + i + "):" );
            for (Edge edge : neighbors.get(i)) {
                System.out.println("(" + getVertex(edge.getU()) + "," + getVertex(edge.getV()) + ")");
            }
            System.out.println();
        }
    }

    @Override
    public void clear() {
        vertices.clear();
        neighbors.clear();
    }

    @Override
    public boolean addVertex(V vertex) {
        
        if (!vertices.contains(vertex)){
            vertices.add(vertex);
            neighbors.add(new ArrayList<Edge>());
            return true;
        }
        return false;
    }

    @Override
    public boolean addEdge(int u, int v) {
        
        return addEdge(new Edge(u,v));
    }

    private boolean addEdge(Edge edge) {
        
        if (!neighbors.get(edge.getU()).contains(edge)){
            
            neighbors.get(edge.getU()).add(edge);
        }
        return false;
    }
}

需要注意的是,上面的那个变量neighbors表示的就是邻接边线性表,这个线性表的每一个元素都是一个列表类型,而这个列表中的元素类型都是Edge对象类型,即存储的都是一个个边对象。它们数据结构如下图所示:

 

 

 neighbors[i]是表示包含顶点i的所有邻接边列表,这里边的都是以i作为出发点的,<i,x>

posted @ 2020-06-13 22:31  有心有梦  阅读(223)  评论(0编辑  收藏  举报