算法思想:采用图的BFS(Breadth-First-Search)广度搜索的贪心算法,广度一遍后比较得出当前最短路径点(贪心),再以该点作为中间点,层层向外扩展,直到遍历所有的图节点。
局限:只能是单源的,注意该算法要求图中不存在负权边。
算法效率:使用邻接矩阵的时间复杂度为O(n^2),用优先队列的复杂度为O(mlogn),本算法效率是O(n^2)。
1.设置当前点集初态,列出V0到各顶点的距离。
2.从V0到当前点集中找出距离最短的点Vj(包括新路径和之前的路径)及相应的路径,并将其余各点的已有路径与经过该路径的新路径比较,若新路径短则更新为新路径。
3.从当前点集中去掉Vj,并重复过程2进行类似处理,直到当前点集为空,即确定了从V0到各点中的最短距离。
图的领接矩阵(带权短阵):
{MAX_INT,7,9,MAX_INT,MAX_INT,14},
{7,MAX_INT,10,15,MAX_INT,MAX_INT},
{9,10,MAX_INT,11,MAX_INT,2},
{MAX_INT,15,11,MAX_INT,6,MAX_INT},
{MAX_INT,MAX_INT,MAX_INT,6,MAX_INT,9},
{14,MAX_INT,2,MAX_INT,9,MAX_INT}
图如下:
求单源点1到其余各个顶点的最短距离?
实现代码:
#include "stdafx.h"
#include<stdio.h>
#define MAX_VERTEX_NUM 100 //最大顶点数
#define MAX_INT 10000 //无穷大
typedef int AdjType;
typedef char VType; //设顶点为字符类型
struct PathType
{
int route[MAX_VERTEX_NUM];//存放v到vi的一条最短路径
int End;
};
//邻接矩阵表示的图
struct Graph
{
VType V[MAX_VERTEX_NUM]; //顶点存储空间
AdjType A[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
};
//Dijkstra算法
//求G(用邻接矩阵表示)中源点v到其他各顶点最短路径,n为G中顶点数
void Dijkstra(Graph * G,PathType path[],int dist[],int v,int n)
{
int i,j,count,min,minIndex;
//visited[n]用来标志源点到某顶点的最短路径是否求出
int *visited=new int[n];
for(i=0;i<n;i++)
{ //1.初始化
visited[i]=0;
dist[i]=G->A[v][i];//v到它的邻接顶点的权为当前最短路径,用这个权值初始化dist[],优先队列(每次找小)
path[i].route[0]=v; //开始结点都是v
path[i].End=0; //路径末尾索引
}
dist[v]=0;
visited[v]=1;//源点到源点本身的最短路径已经求出
count=1;
while(count<=n-1)
{ //求n-1条最短路径
min=MAX_INT;// MAX_INT为无穷大值,需要实际情况设置
//这一部分实现的是优先队列的功能,找最小值
for(j=0;j<n;j++)
{ //找当前最短路径长度
//如果j未被访问过且当前j的距离更短,更新min和minIndex
if( !visited[j] && dist[j]<min ) // 1.无论新更新的,还是之前的路径中,选出最小的
{
minIndex=j;
min=dist[j];
}
}
//当visited[]数组全是1,即合被访问过时,可以退出了。
if(min==MAX_INT)
break;//最短路径求完(不足n-1)条,跳出while循环,考虑非连通图
//贪心选择,选择当前最min的路径
int pEnd = ++path[minIndex].End;//3.当前minIndex选中了,需要++path[minIndex].End得到该最顶点最小路径的当前最大下标值,最大下标值设置为本顶点
path[minIndex].route[pEnd]=minIndex ;// 存放到自己的最短的路径值。输出即可。
visited[minIndex]=1;//表示V到minIndex最短路径求出,标记为已被访问过
for(j=0;j<n;j++)
{ //minIndex求出后,修改dist和path向量,只更新那些未处理过的点
if(!visited[j] && dist[minIndex]+G->A[minIndex][j] < dist[j] ) // 2.当前最短路径距离dist[minIndex]加上可达邻接距离和原来最小距离比较
{
dist[j]=dist[minIndex]+G->A[minIndex][j];//更新最短路径长度
path[j]=path[minIndex];//3.被更新的顶点,设置它前面的最小路径为当前选中的点的路径,这样较远的顶点被更新一次就很快知道了前面的路径。
}
}
count++;
}
delete []visited;
}
int main()
{
int i,j,v=0,n=6;//v为起点,n为顶点个数
Graph G;
//v到各顶点的最短路径向量
PathType* path = new PathType[n];
//v到各顶点最短路径长度向量
int* dist =new int[n];
AdjType a[MAX_VERTEX_NUM][MAX_VERTEX_NUM]=
{
{MAX_INT,7,9,MAX_INT,MAX_INT,14},
{7,MAX_INT,10,15,MAX_INT,MAX_INT},
{9,10,MAX_INT,11,MAX_INT,2},
{MAX_INT,15,11,MAX_INT,6,MAX_INT},
{MAX_INT,MAX_INT,MAX_INT,6,MAX_INT,9},
{14,MAX_INT,2,MAX_INT,9,MAX_INT}
};
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
G.A[i][j]=a[i][j];
}
}
Dijkstra(&G,path,dist,v,n);
for(i=0;i<n;i++)
{
printf("%d到%d的最短路径:",v+1,i+1);
for(j=0;j<=path[i].End;j++)
{
printf("%d ",path[i].route[j]+1);
}
printf("\n");
printf("最短路径长度:%d",dist[i]);//输出为MAX_INT则表示两点间无路径
printf("\n");
}
delete []path;
delete []dist;
return 0;
}