Dijkstra演算法是一種求單源最短路的演算法,即從一個點開始到所有其他點的最短路。其步驟如下:
c語言實現如下:(使用鄰接矩陣儲存)
#include <stdio.h> #include <malloc.h> #define VERTEXNUM 6 //存放最短路徑的邊元素typedef struct edge{ int vertex;int value; struct edge* next;}st_edge;void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value); void displayGraph(int (*edge)[VERTEXNUM]); void displayPath(st_edge** path, int startVertex,int* shortestPath);void dijkstra(int (*edge)[VERTEXNUM], 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(void){ //動態建立存放邊的二維數組 int (*edge)[VERTEXNUM] = (int (*)[VERTEXNUM])malloc(sizeof(int)*VERTEXNUM*VERTEXNUM); int i,j; for(i=0;i<VERTEXNUM;i++){ for(j=0;j<VERTEXNUM;j++){ edge[i][j] = 0; } } //存放頂點的遍曆狀態,0:未遍曆,1:已遍曆 int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM); for(i=0;i<VERTEXNUM;i++){ vertexStatusArr[i] = 0; } printf("after init:\n"); displayGraph(edge); //建立圖 createGraph(edge,0,1,6); createGraph(edge,0,3,5); createGraph(edge,0,2,1); createGraph(edge,1,2,5); createGraph(edge,1,4,3); createGraph(edge,2,4,6); createGraph(edge,2,3,5); createGraph(edge,2,5,4); createGraph(edge,3,5,2); createGraph(edge,4,5,6); printf("after create:\n"); displayGraph(edge);//最短路徑/*儲存的結構如下:path[0]:edge0->NULLpath[1]:edge1->NULLpath[2]:edge1->edge2->NULLpath[3]:edge1->edge2->edge3->NULLpath[4]:edge4->NULL從頂點0到0的最短路徑:從0出發直接到0從頂點0到1的最短路徑:從0出發直接到1從頂點0到2的最短路徑:從0出發到1,從1出發到2......*/st_edge** path = NULL;//儲存最短路徑的權值/*shortestPath[0] = 0;shortestPath[1] = 8;shortestPath[2] = 12;從頂點0到0的路徑是0從頂點0到1的路徑是8從頂點0到2的路徑是12*/int* shortestPath = NULL;//從頂點0開始尋找最短路徑int startVertex = 0;//最短路徑dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr);printf("the path is:\n");displayPath(path,startVertex,shortestPath); free(edge); free(path); return 0; } //建立圖 void createGraph(int (*edge)[VERTEXNUM], int start, int end, int value){ edge[start][end] = value; edge[end][start] = value; } //列印儲存的圖void displayGraph(int (*edge)[VERTEXNUM]){ int i,j; for(i=0;i<VERTEXNUM;i++){ for(j=0;j<VERTEXNUM;j++){ printf("%d ",edge[i][j]); } printf("\n"); } }//列印最短路徑void displayPath(st_edge** path, int startVertex,int* shortestPath){ int i; st_edge* p; for(i=0;i<VERTEXNUM;i++){ printf("Path from %d to %d:",startVertex,i); p = *(path+i); while(p != NULL){ printf("%d(%d) ",p->vertex,p->value); p = p->next; } printf("\n");printf("the count is:%d\n",shortestPath[i]); }}//最短路徑void dijkstra(int (*edge)[VERTEXNUM], st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr){//初始化最短路徑*path = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM); int i,j; for(i=0;i<VERTEXNUM;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;} }//初始化最短路徑的權值*shortestPath = (int *)malloc(sizeof(int)*VERTEXNUM);for(i=0;i<VERTEXNUM;i++){if(i == startVertex){(*shortestPath)[i] = 0;}else{(*shortestPath)[i] = -1;}}//從頂點0開始,則頂點0就是已訪問的 vertexStatusArr[startVertex] = 1; int shortest, distance,start, end, edgeValue, vNum = 1;//如果還頂點還沒有訪問完 while(vNum < VERTEXNUM){ shortest = 9999; for(i=0;i<VERTEXNUM;i++){ //選擇已經訪問過的點 if(vertexStatusArr[i] == 1){ for(j=0;j<VERTEXNUM;j++){ //選擇一個沒有訪問過的點 if(vertexStatusArr[j] == 0){ //選出一條value最小的邊 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++; //將點設定為訪問過 vertexStatusArr[end] = 1; //儲存最短路徑權值(*shortestPath)[end] = shortest;//儲存最短路徑createPath(*path, startVertex, start, end, edgeValue); } }//返回從startVertex到新的頂點的距離int getDistance(int value, int startVertex, int start, int* shortestPath){if(start == startVertex){return value;}else{return shortestPath[start] + value;}}//儲存最短路徑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;}}
c語言實現如下:(使用鄰接表格儲存體)
#include <stdio.h>#include <malloc.h>#define VERTEXNUM 6//存放頂點的鄰接表元素//存放最短路徑的邊元素typedef struct edge{ int vertex;int value; struct edge* next;}st_edge;void createGraph(st_edge** edge, int start, int end, int value);void displayGraph(st_edge** edge);void delGraph(st_edge** edge);void dijkstra(st_edge** edge, st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr);void displayPath(st_edge** path, int startVertex,int* shortestPath);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(void){//動態建立存放邊的指標數組 st_edge** edge = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM);int i;for(i=0;i<VERTEXNUM;i++){edge[i] = NULL;}//存放頂點的遍曆狀態,0:未遍曆,1:已遍曆int* vertexStatusArr = (int*)malloc(sizeof(int)*VERTEXNUM);for(i=0;i<VERTEXNUM;i++){vertexStatusArr[i] = 0;}printf("after init:\n");displayGraph(edge);//建立圖createGraph(edge,0,1,6);createGraph(edge,0,3,5);createGraph(edge,0,2,1);createGraph(edge,1,2,5);createGraph(edge,1,4,3);createGraph(edge,2,4,6);createGraph(edge,2,3,5);createGraph(edge,2,5,4);createGraph(edge,3,5,2);createGraph(edge,4,5,6);printf("after create:\n");displayGraph(edge);//最短路徑/*儲存的結構如下:path[0]:edge0->NULLpath[1]:edge1->NULLpath[2]:edge1->edge2->NULLpath[3]:edge1->edge2->edge3->NULLpath[4]:edge4->NULL從頂點0到0的最短路徑:從0出發直接到0從頂點0到1的最短路徑:從0出發直接到1從頂點0到2的最短路徑:從0出發到1,從1出發到2......*/st_edge** path = NULL;//儲存最短路徑的權值/*shortestPath[0] = 0;shortestPath[1] = 8;shortestPath[2] = 12;從頂點0到0的路徑是0從頂點0到1的路徑是8從頂點0到2的路徑是12*/int* shortestPath = NULL;int startVertex = 0;//最短路徑dijkstra(edge, &path, &shortestPath, startVertex, vertexStatusArr);printf("the path is:\n");displayPath(path,startVertex,shortestPath);delGraph(edge);edge = NULL;delGraph(path);path = NULL;if(vertexStatusArr != NULL){ free(vertexStatusArr); vertexStatusArr = NULL;}if(shortestPath != NULL){free(shortestPath);shortestPath = NULL;} return 0;}//建立圖void createGraph(st_edge** edge, int start, int end, int value){ st_edge* newedge1 = (st_edge*)malloc(sizeof(st_edge)); newedge1->vertex = end;newedge1->value = value; newedge1->next = NULL; st_edge** edge1 = edge + start; while(*edge1 != NULL){ edge1 = &((*edge1)->next); } *edge1 = newedge1;st_edge* newedge2 = (st_edge*)malloc(sizeof(st_edge)); newedge2->vertex = start; newedge2->value = value; newedge2->next = NULL; st_edge** edge2 = edge + end; while(*edge2 != NULL){ edge2 = &((*edge2)->next); } *edge2 = newedge2;}//列印儲存的圖 void displayGraph(st_edge** edge){ int i; st_edge* p; for(i=0;i<VERTEXNUM;i++){ printf("%d:",i); p = *(edge+i); while(p != NULL){ printf("%d(%d) ",p->vertex,p->value); p = p->next; } printf("\n"); }}//列印最短路徑void displayPath(st_edge** path, int startVertex,int* shortestPath){ int i; st_edge* p; for(i=0;i<VERTEXNUM;i++){ printf("Path from %d to %d:",startVertex,i); p = *(path+i); while(p != NULL){ printf("%d(%d) ",p->vertex,p->value); p = p->next; } printf("\n");printf("the count is:%d\n",shortestPath[i]); }}//釋放鄰接表佔用的記憶體void delGraph(st_edge** edge){ int i; st_edge* p; st_edge* del; for(i=0;i<VERTEXNUM;i++){ p = *(edge+i); while(p != NULL){ del = p; p = p->next; free(del); } edge[i] = NULL; } free(edge);}//dijkstra求最短路徑void dijkstra(st_edge** edge, st_edge*** path, int** shortestPath, int startVertex, int* vertexStatusArr){//初始化最短路徑*path = (st_edge**)malloc(sizeof(st_edge*)*VERTEXNUM); int i,j; for(i=0;i<VERTEXNUM;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;} }//初始化最短路徑的權值*shortestPath = (int *)malloc(sizeof(int)*VERTEXNUM);for(i=0;i<VERTEXNUM;i++){if(i == startVertex){(*shortestPath)[i] = 0;}else{(*shortestPath)[i] = -1;}}vertexStatusArr[startVertex] = 1;st_edge* p;int shortest, distance, edgeValue, start, end, vNum = 1;//如果還頂點還沒有訪問完while(vNum < VERTEXNUM){shortest = 9999;for(i=0;i<VERTEXNUM;i++){//選擇已經訪問過的點if(vertexStatusArr[i] == 1){for(j=0;j<VERTEXNUM;j++){//選擇一個沒有訪問過的點 if(vertexStatusArr[j] == 0){p = *(edge+i);while(p != NULL){//如果從startVertex到j的距離小於shortestif((distance = getDistance(p->value, startVertex, i, *shortestPath)) < shortest && p->vertex == j){shortest = distance;edgeValue = p->value;start = i;end = j;}p = p->next;}}}}}vNum++;vertexStatusArr[end] = 1;//儲存最短路徑的權值(*shortestPath)[end] = shortest;//儲存最短路徑createPath(*path, startVertex, start, end, edgeValue);}}//返回從startVertex到新的頂點的距離int getDistance(int value, int startVertex, int start, int* shortestPath){if(start == startVertex){return value;}else{return value + shortestPath[start];}}//儲存最短路徑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;}}