The basic algorithm that programmers must know 8-Dijkstra algorithm (Dijkstra algorithm)

Dijkstra algorithm

Dijkstra algorithm is a typical shortest path algorithm,
used to calculate the shortest path from one node to other nodes.
Its main feature is that it expands to the outer layer with the starting point as the center ( breadth first search idea ), until it expands to the end.

Problem scenario

Insert picture description here

There are 7 nodes (A, B, C, D, E, F, G).
Starting from point G,
the distance to each node of the six nodes A, B, C, D, E, and F is represented by an edge ( Weight), such as A-B distance 5.
How to calculate the shortest distance from G to each other node?
What is the shortest distance from other points to each point?

Code resolution

package basic;

public class Dijkstra
{
    
    
	/*
	 * 看完下面的,我们来总体看下迪杰斯特拉算法的运行策略
	 * 首先访问过的只有一个G,然后找到G能访问的节点中权重最小的
	 * 那就是GA,然后将GA看做一个节点,能访问到的节点中权重最小的
	 * 那就是GAB,然后又看作一个整体,下一个能访问到的节点中权重最小的
	 * 那就是GABE,就是这样的策略
	 */
	public static void main(String[] args)
	{
    
    
//		char[] nodes={ 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
//		int[][] weight=new int[nodes.length][nodes.length];
//		final int N=Integer.MAX_VALUE/2;
//		
//		weight[0]=new int[]{N,5,7,N,N,N,2};  
//		weight[1]=new int[]{5,N,N,9,N,N,3};  
//		weight[2]=new int[]{7,N,N,N,8,N,N};  
//		weight[3]=new int[]{N,9,N,N,N,4,N};  
//		weight[4]=new int[]{N,N,8,N,N,5,4};  
//		weight[5]=new int[]{N,N,N,4,5,N,6};  
//		weight[6]=new int[]{2,3,N,N,4,6,N};
		//上面都是初始化数据
		char[] nodes={
    
     'A', 'B', 'C', 'D', 'E', 'F', 'G' ,'H','I'};
		int[][] weight=new int[nodes.length][nodes.length];
		final int N=Integer.MAX_VALUE/2;		
		
		weight[0]=new int[]{
    
    N,5,7,N,N,N,2,N,N};  
		weight[1]=new int[]{
    
    5,N,N,9,N,N,3,N,N};  
		weight[2]=new int[]{
    
    7,N,N,N,8,N,N,N,N};  
		weight[3]=new int[]{
    
    N,9,N,N,N,4,N,2,N};  
		weight[4]=new int[]{
    
    N,N,8,N,N,5,4,N,N};  
		weight[5]=new int[]{
    
    N,N,N,4,5,N,6,N,N};  
		weight[6]=new int[]{
    
    2,3,N,N,4,6,N,N,N};
		weight[7]=new int[]{
    
    N,N,N,2,N,N,N,N,2};
		weight[8]=new int[]{
    
    N,N,N,N,N,N,N,2,N};
		
		dijkstra(weight, 6);
	}
	public static void dijkstra(int[][] weight,int index)
	{
    
    
		//需要三个额外的变量来保存数据
		//这表示这个节点是否是已经被访问过了
		int[] vistied=new int[weight.length];
		//这表示路径是什么
		String[] paths=new String[weight.length];
		//这表示从出发点到当前节点的距离是多少
		int[] TheLength=new int[weight.length];
		
		//初始化路径
		for(int x=0;x<paths.length;x++)
		{
    
    
			paths[x]=new String(index+"->"+x);
		}
		//初始化出发点
		vistied[index]=1;
		TheLength[index]=0;
		/*
		 * 然后是遍历n-1个节点,因为第一个节点已经遍历过了
		 * 这里每一次都是找和出发点相通的,权重最小的那个节点,
		 * 然后对它进行深一层的遍历,看看它走到下一层后的最小路径是否能更加小
		 * 在这里你可能在想第二重的for循环会不会没有进去,就是那个找MinLength的for循环
		 * 然后让下标temp=-1,其实不会的,在后面的for遍历下一层的时候会改变下一层图的遍历
		 * 就是比如出发点是第零层,然后MinLength是找第二层节点的最小权重,然后下面的for会
		 * 根据第二层的最小权重去找第二层到第三层的最小权重,如果是出发点不能到达的节点
		 * 那么就肯定在第三层或者更加低的层,那么在第二层遍历会修改第三层节点的可达,就是修改权重
		 * 那么循环后再回到上面的寻找下一个最小权重的没有访问过的节点的时候就会可能不是从
		 * 第二层找起,而是直接到更加低的层次找
		 */
		for(int x=1;x<weight.length;x++)
		{
    
    
			int MinLength=Integer.MAX_VALUE/2;
			int temp=-1;
			for(int y=0;y<weight.length;y++)
			{
    
    
				if(vistied[y]==0 && weight[index][y]<MinLength)
				{
    
    
					MinLength=weight[index][y];
					temp=y;
				}
			}
			TheLength[temp]=MinLength;
			vistied[temp]=1;
			/**
			 * 首先是出发点到index节点的距离,然后index这个节点能访问的下一层节点
			 * 如果是从index这个节点出发访问到的下一层节点的距离加上从出发点到index的距离
			 * 比从出发点到index下一层节点的距离(这是不经过index节点的,从其他的路线出发的)小,
			 * 那么就将这TheLength的数组对应的index下一层节点对应的位置进行修改
			 */
			for(int y=0;y<weight.length;y++)
			{
    
    
				if(vistied[y]==0 && weight[index][temp]+weight[temp][y]<weight[index][y])
				{
    
    
					weight[index][y]=weight[index][temp]+weight[temp][y];
					paths[y]=paths[temp]+"->"+y;
				}
			}
		}
		for(int x=0;x<paths.length;x++)
		{
    
    
			if(x!=index)
			{
    
    
				System.out.println(index+"到"+x+"的路径:"+paths[x]+"		权重:"+TheLength[x]);
			}
		}
	}
}

result

60的路径:6->0		权重:2
61的路径:6->1		权重:3
62的路径:6->0->2		权重:9
63的路径:6->5->3		权重:10
64的路径:6->4		权重:4
65的路径:6->5		权重:6
67的路径:6->5->3->7		权重:12
68的路径:6->5->3->7->8		权重:14

note

1. Dijkstra's algorithm only supports graphs with non-negative weights. For
example, in the above example, if BD (-90), then when traversing, first add A into the visited array, and then add B to the already visited array. Visit the array, then it will be determined that the minimum distance from G to A is 2, and to B is 3, instead of passing through the BD line, Dijkstra will not recalculate the node with the smallest weight,
2. Integer.MAX_VALUE is used to represent inter-unreachable
because the addition of two Integer.MAX_VALUE will overflow and cause negative weight

Guess you like

Origin blog.csdn.net/qq_43416157/article/details/108811281