一、迪杰斯特拉
求解图中由起点开始到其他节点的最短路径问题(权值不能为负)。
主要思想:在有权值的图中,直接和起点相连的节点他们的最短路径为和起点相连的边的权值,和起点没有直接相连的节点默认为该点和起点的距离为无穷大。分别保存在两个集合S,U中。S中保存的是已经计算出的距离起点最短路径的节点,U中保存还没有计算的节点。当集合U为空时,算法结束。
如上图,求解A点到其他节点的最短路径。
迪杰斯特拉算法求解过程:
1.将A节点放入到集合S中,其他节点放入集合U中,集合U中保存的节点的权值都是当前节点到起点的最短路径,例如上图中的节点E,当E放入集合U中时,E的权值应该为4,而不是3。因为节点A到E的最短路径为A-C-E。
S={A},U={B,C,D,E,F,G}; 集合U中各节点到起点的权值为UV={6,1,∞,∞,∞,∞},刚开始时,只有和起点直接相连的节点有权值,其他节点权值都默认为无穷大。
2.从集合U中找出权值最小的节点,加入到集合S中并且更新集合U,则S={A,C},U={B,D,E,F,G},此时也应该更新集合U中各节点到起点的权值,将与节点C相连的节点的权值由无穷大更新为经过C点到A点的路径上的权值的和,如果和值比之前的权值小,则更新,否则权值不变。因为和节点C相连的节点只有节点E(已经遍历过的节点不能重复计算),所以此时只需要更新集合U中节点E的权值即可,因为节点E当前的集合中权值为无穷大,所以更新节点E的权值为经过节点C到节点A的路径的权值的和,即为4,UV={6,∞,4,∞,∞}.
3.重复第2步操作,此时S={A,C,E},U={B,D,F,G},集合U中各节点的权值为UV={6,5,6,∞}.
4.重复第2步操作,此时S={A,C,E,D},U={B,F,G},因为节点D和节点B,E,F相连,所以需要更新节点B,E,F的权值,节点D到节点A的权值为5,节点D到节点B的权值为3,节点B经过节点D到节点A的权值为8,大于节点B已存在的到节点A的权值,所以节点B不更新,以此类推,集合U中各节点的权值为UV={6,6,∞}.
5.重复第2步操作,此时S={A,C,E,D,B},U={F,G},集合U中各节点的权值为UV={6,10}.
6.重复第2步操作,此时S={A,C,E,D,B,F},U={G},集合U中各节点的权值为UV={10}.
7.重复第2步操作,此时S={A,C,E,D,B,F,G},U={},集合U中各节点的权值为.
JAVA代码实现:
将上图保存在一个二维数组中(邻接矩阵):
// -1代表无穷大
static int[][] source;
public static void main(String[] args) throws Exception {
source = new int[][] {
{
0, 0, 0, 0, 0, 0, 0, 0 },
{
0, 0, 6, 1, -1, -1, -1, -1 },
{
0, 6, 0, -1, 3, -1, -1, 4 },
{
0, 1, -1, 0, -1, 3, -1, -1 },
{
0, -1, 3, -1, 0, 1, 4, -1 },
{
0, -1, -1, 3, 1, 0, 2, -1 },
{
0, -1, -1, -1, 4, 2, 0,</