数据结构与算法之邻接矩阵及其实现

119 阅读4分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第36天,点击查看活动详情

✨欢迎关注🖱点赞🎀收藏⭐留言✒

🔮本文由京与旧铺原创,csdn首发!

😘系列专栏:算法学习

💻首发时间:🎞2022年12月31日🎠

🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦

🎧作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲


邻接矩阵

因为节点与节点之间的关系就是连通与否,即为0或者1,因此邻接矩阵(二维数组)即是:先用一个数组将顶点保存,然后采用矩阵来表示节点与节点之间的关系。对于某点到本身统一初始化为0,关系图和举例如下:

8 当图中的边带有权重,我们就将权值赋值到邻接矩阵,但是需要注意, 如果边带有权值,并且两个节点之间是连通的,上图中的边的关系就用权值代替,如果两个顶点不通,则使用无穷大或-1代替,在代码实现时也可以将顶点到自身顶点的距离设置为无穷大。

9 下面我们来尝试实现一个邻接矩阵,我们使用类的形式来实现,首先顶点不一定是数字,我们需要一个顶点数组来储存顶点,以字符串形式储存每一个顶点吧,还需要一个二维数组表示邻接矩阵本身,为了完成数组下标与顶点间的映射,最后还需要一个标志位来表示该图是无向图还是有向图。

    //邻接矩阵
    private int[][] matrix;
    //顶点数组
    private String[] points;
    //将顶点与邻接矩阵对应起来
    private HashMap<String, Integer> hash = new HashMap<>();
    //是否是有向图
    private boolean isDirect;

初始化图时,需要一个顶点数组来表示哪些该图中有哪些顶点,并将相关属性初始化,代码如下:

//构造方法
    public GraphMatrix1(String[] points) {
        init(points);
    }
    //初始化
    private void init(String[] points) {
        //传入的顶点数组,顶点不能重复
        this.points = points.clone();
        int size = this.points.length;
        matrix = new int[size][size];
        for (int i = 0; i < size; i++) {
            hash.put(points[i], i);
        }
        //初始化邻接矩阵所有的边
        for (int i = 0; i < size; i++) {
            Arrays.fill(matrix[i], Integer.MAX_VALUE);
        }
    }
    //有向图构造方法
    public GraphMatrix1(String[] points, boolean isDirect) {
        this.isDirect = isDirect;
        init(points);
    }

我们需要一个方法将边添加到图中,添加边时,我们只需将边的起点和终点以及权值传入,如果没有权值取默认值1。 基本思路如下:

  • 获取两个顶点对应的下标值,如果出现-1,即表示有顶点不存在,则直接返回false
  • 根据起点与终点下标,将邻接矩阵赋予对应的权重值。
  • 无权值,以1为默认权值。
    /**
     *
     * @param start 起点
     * @param end 终点
     * @param weight 权重
     * @return 是否添加成功
     */
    public boolean addEdge(String start, String end, int weight) {
        int si = hash.getOrDefault(start, -1);
        int ei = hash.getOrDefault(end, -1);

        if (si == -1 || ei == -1) return false;

        matrix[si][ei] = weight;

        //无向图需要双向赋值
        if(!isDirect) matrix[ei][si] = weight;

        return true;
    }

    /**
     * 添加无权值的边
     * @param start 起点
     * @param end 终点
     * @return 是否添加成功
     */
    public boolean addEdge(String start, String end) {
        return addEdge(start, end, 1);
    }

为了方便测试,我们写一个方法来将邻接矩阵中的数据输出,代码如下:

    //输出邻接矩阵
    public void print() {
        int  n = points.length;
        //输出一行顶点
        System.out.printf("%s\t", " ");
        for (String s : points) System.out.printf("%s\t", s);

        System.out.println();
        //输出矩阵
        int row = matrix.length;
        int col = matrix[0].length;
        for (int i = 0; i < row; i++) {
            System.out.printf("%s\t", points[i]);
            for (int j = 0; j < col; j++) {
                if (matrix[i][j] != Integer.MAX_VALUE) System.out.printf("%d\t", matrix[i][j]);
                else System.out.printf("%s\t", "∞");
            }
            System.out.println();
        }
    }

测试代码:

    public static void testMa1() {
        String[] s = {"1", "2", "3", "4"};
        //无向图测试
        GraphMatrix1 gm1 = new GraphMatrix1(s);
        //无权值
        gm1.addEdge("1", "2");
        gm1.addEdge("1", "3");
        gm1.addEdge("1", "4");
        gm1.addEdge("3", "2");
        gm1.addEdge("4", "3");
        //输出
        System.out.println("无向图,无权值:");
        gm1.print();
        //无向图测试
        GraphMatrix1 gm2 = new GraphMatrix1(s);
        //无权值
        gm2.addEdge("1", "2", 4);
        gm2.addEdge("1", "3", 7);
        gm2.addEdge("1", "4", 6);
        gm2.addEdge("3", "2", 5);
        gm2.addEdge("4", "3", 3);
        //输出
        System.out.println("无向图,有权值:");
        gm2.print();

        //有向图测试
        GraphMatrix1 gm3 = new GraphMatrix1(s, true);
        //无权值
        gm3.addEdge("1", "2");
        gm3.addEdge("1", "3");
        gm3.addEdge("1", "4");
        gm3.addEdge("3", "2");
        gm3.addEdge("4", "3");
        //输出
        System.out.println("有向图,无权值:");
        gm3.print();
        //有向图测试
        GraphMatrix1 gm4 = new GraphMatrix1(s, true);
        //有权值
        gm4.addEdge("1", "2", 4);
        gm4.addEdge("1", "3", 7);
        gm4.addEdge("1", "4", 6);
        gm4.addEdge("3", "2", 5);
        gm4.addEdge("4", "3", 3);
        //输出
        System.out.println("有向图,有权值:");
        gm4.print();
    }

测试结果:

22 与我们所画的分析图结果是一致的。