我写的这个是错误的。才发现之前是自己理解错了,请不要参考。
不过可以作为错误样例参考。错误原因,第三步,对距离值进行修改,修改的是还未求出权值的顶点的最短路径,而不是已经求出权值的点。虽然最后实现的结果是对的,但因为这里弄错了一丁点,导致整个代码量加了很多。(当初理解错了这个算法,觉得这么做好幼稚,还默默地在心里鄙视过这个算法,渣渣的任性太可笑了)。本来想删了这篇,想想还是算了吧。权当一个不认真学习算法的教训的记录吧。
一个有向图,指定一个源点,求它到其他结点的最短路径。
算法步骤如下:
G={V,E}
1. 初始时令 S={V0},T=V-S={其余顶点},T中顶点对应的距离值
若存在<V0,Vi>,d(V0,Vi)为<V0,Vi>弧上的权值
若不存在<V0,Vi>,d(V0,Vi)为∞
2. 从T中选取一个与S中顶点有关联边且权值最小的顶点W,加入到S中
3. 对其余T中顶点的距离值进行修改:若加进W作中间顶点,从V0到Vi的距离值缩短,则修改此距离值
重复上述步骤2、3,直到S中包含所有顶点,即W=Vi为止
baidu百科给的思路,基本上按照这个步骤写的,首先找到所有能从源点直接到达的点,得到它们的最短路径。
重复操作:遍历所有和已经确定了最短路径的点相关联的路径,选出权值最小的路径,得到其对应的结点的最小路径值,然后再检查一下原有的结点,是否因为加入了新的结点,而多了一条更短的路径。
重复n-1次。(共n个点)
我这里直接定义一个固定大小的图,录入的图的结点也许只有几个,并未另外计算到底有几个结点,每次遍历的时候都全部遍历一遍,因为那些不存在的点初始的最小路径值都为无穷大(这里用999表示),最后输出只要是999的即为到达不了,不输出,不过这样做虽然不影响,但浪费了空间和时间。其实可以在录入数据之后,动态分配空间建立图。
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXNUM 9
int graph[MAXNUM][MAXNUM];
int D[MAXNUM];//用来存放到达对应顶点的最小路径
int final[MAXNUM];//用来标志是否已求出最短路径
int V0;
using namespace std;
void createGraph(int V1,int V2,int weight)//V1->V2
{
graph[V1][V2]=weight;
}
void inputGraph()//将图的结点读入
{
char ch;
int V1,V2,weight;
do
{
cin>>ch;
if (ch!='#')
V1=ch-'0';
else break;
cin>>V2;
cin>>weight;
createGraph(V1,V2,weight);
}
while (1);
}
int shortestPath(int Vj)//用来检查时判断是否某些点又有了更短的路径
{
int i;
int temp=999;
for (i=0; i<MAXNUM; i++)
{
if ((graph[i][Vj]>0)&&(graph[i][Vj]+D[i]<temp))
temp=graph[i][Vj]+D[i];
}
if (temp!=999) D[Vj]=temp;
return temp;
}
void Dijkstra()
{
int i,j,k,Va,Vb,temp;
D[V0]=0;
final[V0]=1;
for (i=0; i<MAXNUM; i++)//找出所有从源点可直接到达的点,得到暂时的最小路径
{
if (i!=V0)
{
if (graph[V0][i]>0)
D[i]=graph[V0][i];
else
D[i]=999;
}
}
for (i=1; i<MAXNUM; i++) //重复n-1次
{
temp=999;
for (j=0; j<MAXNUM; j++)
{
if (1==final[j])
{
for (k=0; k<MAXNUM; k++)
{
if ((graph[j][k]>0)&&(0==final[k])&&(graph[j][k]<temp))
{
temp=graph[j][k];
Va=j;
Vb=k;
}
}
}
}
if (temp!=999)
{
final[Vb]=1;
D[Vb]=temp;
}
//对已经确定的顶点再做修改
for (j=0; j<MAXNUM; j++)
{
if (1==final[j])
{
shortestPath(j);
}
}
}
}
void display()
{
int i;
cout<<"从"<<V0<<"出发,到达各点的最小路径为:"<<endl;
for (i=0; i<MAXNUM; i++)
{
if (D[i]!=999)
cout<<i<<":"<<D[i]<<endl;
}
}
int main()
{
cout<<"请输入各边的权值,以#结束:(格式:顶点1 顶点6 权值3),"<<endl;
inputGraph();//将图的信息读入,创建图
cout<<"请输入源点"<<endl;
cin>>V0;
Dijkstra();
display();
return 0;
}