开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第36天,点击查看活动详情
✨欢迎关注🖱点赞🎀收藏⭐留言✒
🔮本文由京与旧铺原创,csdn首发!
😘系列专栏:算法学习
💻首发时间:🎞2022年12月31日🎠
🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦
🎧作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲
邻接矩阵
因为节点与节点之间的关系就是连通与否,即为0或者1,因此邻接矩阵(二维数组)即是:先用一个数组将顶点保存,然后采用矩阵来表示节点与节点之间的关系。对于某点到本身统一初始化为0,关系图和举例如下:
当图中的边带有权重,我们就将权值赋值到邻接矩阵,但是需要注意, 如果边带有权值,并且两个节点之间是连通的,上图中的边的关系就用权值代替,如果两个顶点不通,则使用无穷大或-1代替,在代码实现时也可以将顶点到自身顶点的距离设置为无穷大。
下面我们来尝试实现一个邻接矩阵,我们使用类的形式来实现,首先顶点不一定是数字,我们需要一个顶点数组来储存顶点,以字符串形式储存每一个顶点吧,还需要一个二维数组表示邻接矩阵本身,为了完成数组下标与顶点间的映射,最后还需要一个标志位来表示该图是无向图还是有向图。
//邻接矩阵
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();
}
测试结果:
与我们所画的分析图结果是一致的。