求最短路径Dijkstra算法C++

来源:互联网 发布:你瞒我瞒网络歌手 编辑:程序博客网 时间:2024/05/22 10:24

我写的这个是错误的。才发现之前是自己理解错了,请不要参考。

不过可以作为错误样例参考。错误原因,第三步,对距离值进行修改,修改的是还未求出权值的顶点的最短路径,而不是已经求出权值的点。虽然最后实现的结果是对的,但因为这里弄错了一丁点,导致整个代码量加了很多。(当初理解错了这个算法,觉得这么做好幼稚,还默默地在心里鄙视过这个算法,渣渣的任性太可笑了)。本来想删了这篇,想想还是算了吧。权当一个不认真学习算法的教训的记录吧。




一个有向图,指定一个源点,求它到其他结点的最短路径。

算法步骤如下:
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 9int 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;}


0 0
原创粉丝点击