C language Dijkstra algorithm to find the shortest path detailed explanation

prepare a map

Stealing a picture of an unknown friend, hee hee.insert image description here

Algorithm example description

Purpose: To find a shortest path between point A and point B in a map (in fact, each operation of the algorithm will find a shortest path from point A to each other point).
Process:
1) Take the example from point 1 to point 4.
2) Mark location 1. (The role of marking will be realized later. When all the locations are marked, the shortest path will be found!), at this time draw on the draft (99 is not directly reachable)

线路  距离总和
1->2  2
1->3  5
1->4  99
1->5  99
1->6  99
1->7  99

3) Through comparison, we can get that the distance 1->2 is the shortest, then we mark the No. 2 location at this time to indicate that we have found the shortest distance from No. 1 to No. 2. So at this time, can we shorten the distance from No. 1 to places other than No. 2? Comparing 1->3 and 1->2->3, we can see that the distance of 1->2->3 is 4, which is shorter. Modify 1 The route and distance from No. 3 to No. 3, and then compare the remaining unmarked site routes in turn. Then revise the draft

线路  		距离总和
1->2  		2
1->2->3  	4
1->2->4  	6
1->2->5  	8
1->6  		99
1->7  		99

4) By comparison, we can get the shortest distance between No. 1 and No. 3 among the unmarked locations. It can be seen that the shortest path between No. 1 and No. 3 has also been concluded. Then mark No. 3. At this time, the distance from No. 1 to the unmarked location is closer to the original route, or go to No. 3 first, and go closer from No. 3, and compare. Take number 4 as an example. In the last conclusion, 1->2->4=6, now 1->2->3->4=5, which is shorter, modify the route; then compare numbers 1 to 5 in turn , No. 1 to No. 6, and No. 1 to No. 7. The shortest distance can be modified to be shorter.

线路  			距离总和
1->2  			2
1->2->3  		4
1->2->3->4  	5
1->2->5  		8
1->2->3->6  	7
1->7  			99

5) According to the above rules, mark No. 4 at this time, compare and modify to get No. 5, 6, and 7 locations with shorter distances

线路  			距离总和
1->2  			2
1->2->3  		4
1->2->3->4  	5
1->2->5  		8
1->2->3->4->6  	6
1->2->3->4->7  	9

6) According to the above rules, mark No. 6 at this time, compare and modify to get No. 5 and No. 7 locations with shorter distances

线路  				距离总和
1->2  				2
1->2->3  			4
1->2->3->4  		5
1->2->5  			8
1->2->3->4->6  		6
1->2->3->4->6->7  	8

7) According to the above rules, mark No. 5 at this time (the two distances are the same, choose one at random), compare and modify to get No. 7 location with a shorter distance

线路  				距离总和
1->2  				2
1->2->3  			4
1->2->3->4  		5
1->2->5  			8
1->2->3->4->6  		6
1->2->3->4->6->7  	8

8) Mark location No. 7, and there are no unmarked locations at this time, which means that all locations have found the shortest path from No. 1 to it! Algorithm ends.

Algorithm summary

Find the shortest path from A to B
1. In the location set Map, mark A first.
2. Store the path and distance from A to other places directly, choose the shortest one, assuming it is A->C, then mark C at this time, indicating that the shortest path from A to C has been found, and compare A->other distances For the distance from A->C->Other, if the route passing through C is relatively short, modify A->Other to A->C->Other, and update its current shortest distance in time.
3. Repeat step 2 until all locations are marked.
4. A->…->B path and distance in the output result (… means 0 to multiple intermediate points).

Code

Save the map with a map structure

//最大地点数 
#define MAXCOUNT 20
//不可能距离值(两地点无直接线路时) 
#define MAXDISTANCE 99
//地图结构 
typedef struct map
{
    
    
	//地点数量 
	int nodeCount;
	//地点标识 
	int id[MAXCOUNT];
	//各地点间距离 distance[i][j]=distance[j][i],表示i地点和j地点的距离 
	int distance[MAXCOUNT][MAXCOUNT]; 
}Map; 

Since there are many lines on the map, the file reading method is used here to write map.txt, and the format is the
number of locations n1
the number of lines n2
n2 (the id of location a, the distance between id a and b of location b)

7
12
1 2 2
1 3 5
2 3 2
2 5 6
2 4 4
4 3 1
3 6 3
4 5 4
4 6 1
4 7 4
5 7 1
6 7 2

Write a file to read into the map function

//读取map.txt中的信息 
void readMap(Map *map)
{
    
    
	//以读形式打开文件 
	FILE *fp=fopen("map.txt","r");
	//读取地点数量 
	fscanf(fp,"%d",&map->nodeCount);
	int n;
	//读取路线数量 
	fscanf(fp,"%d",&n);
	int i,j;
	//初始化地点id
	for(i=1;i<=map->nodeCount;i++)
	{
    
    
		map->id[i]=i;	
	} 
	//初始化每两地点均无路线
	for(i=1;i<MAXCOUNT;i++)
	{
    
    
		for(j=1;j<MAXCOUNT;j++)
		{
    
    
			map->distance[i][j]=MAXDISTANCE;	
		}		
	}	
	//读入线路
	int k,d;
	for(k=1;k<=n;k++)
	{
    
    
		fscanf(fp,"%d%d%d",&i,&j,&d);
		map->distance[i][j]=d;
		map->distance[j][i]=d;
	} 
	//关闭文件
	fclose(fp); 
} 

Write a print map function

//打印地图信息 
void displayMap(Map map)
{
    
    
	int i,j;
	printf("地点个数:%d\n",map.nodeCount);
	printf("各地点间距离(...表示无路线):\n");
	printf("    ");
	for(i=1;i<=map.nodeCount;i++)
	{
    
    
		printf("%-3d ",i);
	}
	printf("\n");
	for(i=1;i<=map.nodeCount;i++)
	{
    
    
		printf("%-3d ",i);
		for(j=i;j<=map.nodeCount;j++)
		{
    
    
			if(map.distance[i][j]==MAXDISTANCE)
			{
    
    
				printf("... ");
			}
			else
			{
    
    
				printf("%-3d ",map.distance[i][j]);	
			}
		}	
		printf("\n");
	} 
	printf("\n");
}

Write path structure

//路线结构 
typedef struct road
{
    
    
	//经过地点id 
	int path[MAXCOUNT];
	//距离
	int minDistance; 
	//经过的地点数
	int count; 
}Road; 

Dijkstra's algorithm implements the shortest path from point a to other points

//迪杰斯特拉算法求地点a到其他地点的最短路径 
Road *djstl(Map map,int id_a)
{
    
    
	//所有路线 
	Road r[MAXCOUNT];
	//标记数组(0为未标记,1为已标记) 
	int flag[MAXCOUNT]={
    
    0};
	
	int i;
	//初始化所有路线 
	for(i=1;i<=map.nodeCount;i++)
	{
    
    
		/*a地点到其他各个地点的距离*/
		/*起点是a,终点是i*/
		r[i].count=2;
		r[i].path[0]=id_a;
		r[i].path[1]=i;
		r[i].minDistance=map.distance[id_a][i];	
	} 
	
	//标记a
	flag[id_a]=1;
	
	//还有未标记地点则循环执行 
	while(1)
	{
    
    
		//寻找a到未标记的地点的最短路线的下标 
		int index=-1;
		for(i=1;i<=map.nodeCount;i++)
		{
    
    
			//未标记 
			if(flag[i]==0)	
			{
    
    
				if(index==-1)
				{
    
    
					index=i;
				}
				else if(r[i].minDistance<r[index].minDistance)
				{
    
    
					index=i;
				}
			}
		}	
		//不存在未标记下标了 
		if(index==-1)
		{
    
    
			return r;
		}
		//标记index
		flag[index]=1; 
		//比较并修改其他路线此时的最短路径 
		for(i=1;i<=map.nodeCount;i++)
		{
    
    
			//未找到最短路径的地点 
			if(flag[i]==0)
			{
    
    
				//a->...->i短还是a->...->index->i短,后者短,则说明a到i有更好的选择 
				if(r[i].minDistance>r[index].minDistance+map.distance[index][i]) 
				{
    
    
					/*将r[index]的值赋予r[i],并修改r[i]的最短路径*/
					r[i].count=r[index].count+1;
					int j;
					for(j=0;j<r[i].count-1;j++)
					{
    
    
						r[i].path[j]=r[index].path[j];
					}
					r[i].path[j]=i;
					r[i].minDistance=r[index].minDistance+map.distance[index][i];
				}
			}
		}
	} 
}

output the requested path

//打印a到b的最短路径 
void displayRoad(Road rab)
{
    
    
	printf("距离:%d\n",rab.minDistance);
	int i;
	printf("路线:");
	for(i=0;i<rab.count-1;i++)
	{
    
    
		printf("%d-->",rab.path[i]);
	}
	printf("%d\n\n",rab.path[i]);
}

Write the main function test

int main()
{
    
    
	//地图变量 
	Map map;
	//读取地图 
	readMap(&map);
	//打印地图信息 
	displayMap(map);
	
	int id_a,id_b;
	printf("id_a:");
	scanf("%d",&id_a);
	printf("id_b:");
	scanf("%d",&id_b);
	
	printf("搜索最短路径中,请稍后...\n");
	Road *r=djstl(map,id_a);
	printf("搜索最短路径完毕!\n");
	displayRoad(r[id_b]);
	return 0;
}

Test the shortest path from No. 1 to No. 4.
insert image description here
Test the shortest distance from No. 1 to No. 7.
insert image description here
The result is consistent with the calculation above, and the realization is completed!

Guess you like

Origin blog.csdn.net/qq_36694133/article/details/104301906