Dijkstra算法
1.定义概览
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点(节点需为源点)到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,注意该算法要求图中不存在负权边。
实例:假设有A,B,C,D四个城市,(这里讨论的是有向网) 它们的距离为: A->B(10),A->C(11),B->D(12),C->D(13);
所谓単源路径就是解决从源点 A开始找出到其他城市的最短距离(除本身外的其他所有城市)。Dijkstra算法可以求出A->B(10),A->C(11),A->D(22);
拓展2:多源最短路径(常用Floyd算法)是解决任意两点间的最短路径的一种算法,(不局限于从源点出发,到其他各个顶点 )可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd算法的时间复杂度为O(N3),空间复杂度为O(N2)。
代码
/*
@ Dijkstra算法(単源最短路径)
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#define MAXV 100
#define LIMITLESS 9999 //定义为无穷大,默认为节点间不存在联系
using namespace std;
typedef struct
{
char info; //顶点其他信息
}VertexType;
typedef struct MGraph
{
int v; //顶点数
int e; //边数
int edges[MAXV][MAXV];//邻接矩阵的数组表现
VertexType vexs[MAXV]; //顶点信息
}MGraph;
void creat(MGraph *G)
{
int i, j, k, w;
int start, end;
printf("请输入顶点数和边数:\n");
scanf("%d%d", &(G->v), &(G->e));
getchar();
printf("请输入顶点信息:\n");
for (i = 0; i<G->v; i++)
{
scanf("%c", &(G->vexs[i].info));
}
for (i = 0; i<G->v; i++)
{
for (j = 0; j<G->v; j++)
{
G->edges[i][j] = LIMITLESS;
}
}
printf("输入图的顶点边的下标值和它的权值:\n");
for (k = 0; k<G->e; k++)
{
scanf("%d%d%d", &start, &end, &w);
G->edges[start][end] = w;
}
}
void print(MGraph *G)
{
int i, j;
printf("顶点数:%d,边数:%d\n", G->v, G->e);
printf("%d个顶点的信息:\n", G->v);
for (i = 0; i<G->v; i++)
{
printf("%5c",G->vexs[i].info);
}
printf("\n各个顶点的连接情况:\n");
printf("\t");
for (i = 0; i<G->v; i++)
{
printf("[%d]\t", i);
}
printf("\n");
for (i = 0; i<G->v; i++)
{
printf("[%d]\t", i);
for (j = 0; j<G->v; j++)
{
if (G->edges[i][j] == LIMITLESS)
{
printf("oo\t");
}
else
{
printf("%d\t", G->edges[i][j]);
}
}
printf("\n");
}
}
void Ppath(MGraph *g,int path[], int i, int v) //前向递归查找路径上的顶点,但不包含起点与终点的路径值
{
int k;
k = path[i];
if (k == v) //无中间节点,退出
{
return;
}
Ppath(g,path, k, v);
printf("%c",g->vexs[k]);
}
void Dispath(MGraph *g,int dist[], int path[], int s[], int n, int v)
{
int i;
for (i = 0; i < n; i++)
{
if (s[i] == 1)
{
printf("从%c到%c的最短路径长度为:%d\t路径为:", g->vexs[v], g->vexs[i], dist[i]);
printf("%c",g->vexs[v]); //输出路径上的起点
Ppath(g,path, i, v); //输出路径上的中间点
printf("%c\n",g->vexs[i]); //输出路径上的终点
}
else
{
printf("从%c到%c不存在路径\n", g->vexs[v], g->vexs[i]);
}
}
}
void Dijkstra(MGraph *g, int v)
{
int mindis, i, j, u;
int s[MAXV]; //表示这个顶点是否存入最短路线中(0表示未加入,1表示已加入)
int dist[MAXV]; //表示起始点到此顶点的距离
int path[MAXV];//表示此点的上一步是哪一个顶点
for (i = 0; i < g->v; i++)
{
s[i] = 0;
dist[i] = g->edges[v][i];
if (g->edges[v][i] < LIMITLESS)
{
path[i] = v;
}
else
{
path[i] = -1;
}
}
s[v] = 1;
path[v] = 0;
for (i = 0; i < g->v; i++)
{
mindis = LIMITLESS; //mindis置最小长度初值
for (j = 0; j < g->v; j++) //选取不在s中且具有最小距离的顶点u
{
if (s[j] == 0 && dist[j] <mindis)
{
mindis = dist[j];
u = j;
}
}
s[u] = 1;
for (j = 0; j < g->v; j++)
{
if (s[j] == 0)
{
if (g->edges[u][j] < LIMITLESS&&dist[u] + g->edges[u][j] < dist[j])
{
dist[j] = dist[u] + g->edges[u][j];
path[j] = u;
}
}
}
}
Dispath(g ,dist, path, s, g->v, v);
}
int main(void)
{
MGraph *g;
g = (MGraph *)malloc(sizeof(MGraph));
creat(g);
print(g);
Dijkstra(g,0);
return 0;
}