算法思路
节点有多个后继节点时先遍历边权重小的
指定一个起始节点
把当前节点所有后继节点按路径权值升序排序并加入到集合中
按顺序弹出后继节点,将此节点的所有未被遍历的后继节点按权值升序排序加入集合
重复弹出集合首元素以及把该元素后继节点加入集合直到集合为空
算法实现
图的实现
此实现方法没有节点类
用枚举类型UNDISCOVERD表示未被发现,VISITED表示已被访问
采用邻接矩阵和顶点索引
邻接矩阵int[][] matrix(邻接矩阵无需设置为沿对角线对称)
matrix[i][j]表示从索引i的节点指向索引j的节点的权值
权值为0表示两点不连接或者自身与自身不连接
List toVisit保存"整个"遍历过程待访问的节点
public class Graph {
private int N; // 节点个数
public int[][] matrix; // 邻接矩阵
private Status[] statuses; // 保存每个节点的状态
private T[] datas; // 保存每个节点的数据
private List toVisit = new ArrayList<>(); // 保存整个遍历过程待访问的节点
}
enum Status { // 节点对象的状态
// 未被发现, 已被遍历
UNDISCOVERD, VISITED
}
重点
将当前节点的后继节点按权值排序并加入集合
遍历每个节点,查看邻接矩阵
如果matrix[index][i] > 0则说明当前节点有边指向索引i的节点,然后再判断该节点是否被访问过,跳过被访问过的节点
按权值排序需要重写compare()方法(默认升序)
o1 和o2 是两个对象也即两节点索引,return matrix[index][o1] - matrix[index][o2]的作用是,集合调用sort()方法进行排序时,按前当前节点指向索引o1节点的边权重减去当前节点指向索引o2节点的边权重,小于0(前一条边的权重小)则两条边的位置不变,大于0则交换位置(大概意思是这样)
将当前节点后继节点的集合合并addAll()到整个遍历过程的待访问集合
this.toVisit是图对象的成员变量,记录整个遍历过程的待访问节点
toVisit是当前方法的局部变量记录当前节点的后继待访问节点
如果不用局部变量toVisit而只用this.toVisi