某个源点到其余各顶点的最短路径,这个问题有一个经典算法,那就是Dijkstra提出的一个按路径的长度递增的顺序产生的最短路径的算法。其总体思路就是通过一个辅助的数组用于存储某个顶点到目标顶点的所有路径长度,按照递增的顺序来存储,然后取最小值,就是最短路径。
基于以上分析,可以得到如下的描述算法:
书上提供的图,作为参考:
下面把代码和测试用例共享出来:
/*
************************************************
*Name : Matrix_Dijkstra.c *
*Date : 2015-06-08 *
*Author : sniper *
*Aim : Matrix storage the graph and using the *
* Dijkstra algrithm to find the way v0 to *
* every node. *
************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int node_count=0,weight=0,edge_count=0;
/*
*storage the shotest edge
*/
typedef struct edge{
int vertex;
int value;
struct edge* next;
}st_edge;
void displayGraph(int (*edge)[node_count]);
void displayPath(st_edge** path, int startVertex,int* shortestPath);
void dijkstra(int (*edge)[node_count], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr);
int getDistance(int value, int startVertex, int start, int* shortestPath);
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue);
int main()
{
int i;
int node_pair1,node_pair2;
int* vertexStatusArr;
int* shortestPath = NULL;
int startVertex = 0;
printf("please input the number of node and edge: ");
scanf("%d %d",&node_count,&edge_count);
int (*edge)[node_count] = (int (*)[node_count])malloc(sizeof(int)*node_count*node_count);
memset(edge,0,sizeof(edge));
/*
*storage the visit status of node
*0 not vist 1 visit
*/
vertexStatusArr = (int*)malloc(sizeof(int)*node_count);
for(i=0;i<node_count;i++){
vertexStatusArr[i] = 0;
}
printf("after init:\n");
displayGraph(edge);
/*
*Create the graph
*/
for(i=0;i<edge_count;i++)
{
printf("please input the node pair: ");
/*
*node_pair1 node_pair2 two side of edge and
*the weight means the weight of edge
*/
scanf("%d %d %d",&node_pair1,&node_pair2,&weight);
edge[node_pair1][node_pair2] = weight;
}
printf("after create:\n");
displayGraph(edge);
st_edge** path = NULL;
/*
*from the v0 to find the way
*/
startVertex = 0;
/*
*Dijkstra algrithm
*/
dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr);
printf("***********************************************\n");
printf("the path is:\n");
displayPath(path,startVertex,shortestPath);
free(edge);
free(path);
return 0;
}
/*
*print the graph
*/
void displayGraph(int (*edge)[node_count])
{
int i,j;
for(i=0;i<node_count;i++)
{
for(j=0;j<node_count;j++)
{
printf("%d ",edge[i][j]);
}
printf("\n");
}
}
/*
*print the shortest path
*/
void displayPath(st_edge** path, int startVertex,int* shortestPath)
{
int i;
st_edge* p;
for(i=1;i<node_count;i++)
{
if(shortestPath[i]==-1)
{
printf("No way to %c node!\n",i+'A');
continue;
}
printf("Path from %c to %c:",startVertex+'A',i+'A');
p = *(path+i);
while(p != NULL)
{
printf("%c(%d) ",p->vertex+'A',p->value);
p = p->next;
}
printf("\n");
printf("the count is:%d\n",shortestPath[i]);
}
}
/*
*Dijkstra find the shortest path
*/
void dijkstra(int (*edge)[node_count], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr)
{
int i=0,j=0;
int shortest=0, distance=0,start=0, end=0, edgeValue=0, vNum = 1;
/*
*init the shortest path
*/
*path = (st_edge**)malloc(sizeof(st_edge*)*node_count);
for(i=0;i<node_count;i++)
{
if(i == startVertex)
{
st_edge* e = (st_edge*)malloc(sizeof(st_edge));
e->vertex = startVertex;
e->value = 0;
e->next = NULL;
(*path)[i] = e;
}
else
(*path)[i] = NULL;
}
/*
*Init the shortest path weight
*/
*shortestPath = (int *)malloc(sizeof(int)*node_count);
for(i=0;i<node_count;i++){
if(i == startVertex){
(*shortestPath)[i] = 0;
}else{
(*shortestPath)[i] = -1;
}
}
/*
*from the v0 to visit
*/
vertexStatusArr[startVertex] = 1;
/*
*find the way v0 to other node
*/
while(vNum < node_count)
{
shortest = 9999;
for(i=0;i<node_count;i++)
{
/*
*choice the node has been visited
*/
if(vertexStatusArr[i] == 1)
{
for(j=0;j<node_count;j++)
{
/*
*choice the node has not been visited
*/
if(vertexStatusArr[j] == 0)
{
/*
*choice the node that distance is minist
*/
if(edge[i][j] != 0 && (distance = getDistance(edge[i][j], startVertex, i, *shortestPath)) < shortest)
{
shortest = distance;
edgeValue = edge[i][j];
start = i;
end = j;
}
}
}
}
}
vNum++;
if(shortest == 9999)
continue;
/*
*make the node set visited
*/
vertexStatusArr[end] = 1;
/*
*visit the shortest path weight
*/
(*shortestPath)[end] = shortest;
/*
*create the shortest path
*/
createPath(*path, startVertex, start, end, edgeValue);
}
}
/*
*get the distance from the v0 to new node
*/
int getDistance(int value, int startVertex, int start, int* shortestPath){
if(start == startVertex){
return value;
}else{
return shortestPath[start] + value;
}
}
/*
*Save the shortest path
*/
void createPath(st_edge **path, int startVertex, int start, int end, int edgeValue){
if(start == startVertex){
st_edge* newEdge = (st_edge*)malloc(sizeof(st_edge));
newEdge->vertex = end;
newEdge->value = edgeValue;
newEdge->next = NULL;
st_edge** p = path + end;
while((*p) != NULL){
p = &((*p)->next);
}
*p = newEdge;
}else{
st_edge** pCopySrc = path + start;
st_edge** pCopyDes = path + end;
st_edge* newEdge = NULL;
while((*pCopySrc) != NULL){
newEdge = (st_edge*)malloc(sizeof(st_edge));
*newEdge = **pCopySrc;
newEdge->next = NULL;
*pCopyDes = newEdge;
pCopySrc = &((*pCopySrc)->next);
pCopyDes = &((*pCopyDes)->next);
}
newEdge = (st_edge*)malloc(sizeof(st_edge));
newEdge->vertex = end;
newEdge->value = edgeValue;
newEdge->next = NULL;
*pCopyDes = newEdge;
}
}
测试用例提供两组:
6 8
0 2 10
0 4 30
0 5 100
1 2 5
2 3 50
3 5 10
4 3 20
4 5 60
6 10
0 1 6
0 3 5
0 2 1
1 2 5
1 4 3
2 4 6
2 3 5
2 5 4
3 5 2
4 5 6
第一组测试用例图是
测试用例2的图:
同样大家可以去我的Github clone
https://github.com/cremyos/Graph_Dijkstra
对于Dijkstra算法只能解决一个节点到其他节点的最短路径,那么如果有多个节点到其他节点的最短路径怎么办,下一篇会和大家分享Floyd算法,敬请期待!