单源点最短路径Dijkstra和Bellmanford

来源:互联网 发布:手机壁纸软件may 编辑:程序博客网 时间:2024/05/16 14:25

单源点最短路径Dijkstra和Bellmanford

Dijikstra算法精髓在于维护了两个集合s和v,而这也是实际编程中实现起来比较头疼的事情,我的做法是把每个节点都设置成一个结构体,里面有个状态变量,为‘s’则意味着它在S集合当中。
另外还有很多小的细节需要注意
- 在C语言中实现时初始的邻接矩阵表示(没有的边可以用很大的数来表示)
- 在松弛过程中注意不要局限于在V集合中的那些点,在S集合中的点也有可能被松弛(但是这种情况只会出现在图中有零环的情况,下面一个例子就是这样的)
- 选取值最小的点。下例由于点数少,所以我直接两个for循环找最小,如果图大的话就要选用好的算法了


代码块

代码块语法遵循标准markdown代码,例如:

#include<stdio.h>#include<stdlib.h>#define n 5#define m 9999//结构体数组,node代表着一个结点,d为源点到此点的距离,state代表它是集合s中的还是v中的 struct {    int d;    char state;}node[n];//松弛,代表把j加入到S后 应该做的一系列动作 void relax(int j,int A[5][5]){    for(int i=0;i<n;i++){            if((A[j][i]!=m)&&(node[j].d+A[j][i]<node[i].d))            {node[i].d=node[j].d+A[j][i];}        }}int main(){    //先初始化node[n];    int min,i,j;    int s=0;    node[0].d=0;    node[0].state='v';     for(int i=1;i<n;i++){        node[i].d=m;        node[i].state='v';    }    int A[5][5]={{m,-1,3,m,m},{m,m,3,2,2},{m,m,m,m,m},{m,1,5,m,m},{m,m,m,-3,m}};    //然后对d进行排序,把最小的那个state记作s,表示它不在松弛范围内    while(s!=n){    //一直到所有的state为s为止//下面两个for是为了找到v中最小的那个 for(i=0;i<n;i++){    if(node[i].state=='v') {    min=node[i].d;    j=i;    break;    }}for(i=0;i<n;i++){    if((node[i].state=='v')&&(node[i].d<min) )        {            min=node[i].d;j=i;        }    }    //j目前记录了最小的d值,下面把state变s,且把s集合的记录数加1 node[j].state='s';s++;    relax(j,A);}for(int i=0;i<n;i++){    printf("%d ",node[i].d);}//然后输出数组d[i];就是单元点A到各个点的最短路径。 

Bellmanford

#include<stdio.h>#include<stdlib.h>#define n 5#define m 9999 //Bellman-Ford算法 int main(){    int t=1;int A[5][5]={{m,-1,3,m,m},  {m,m,3,2,2},  {m,m,m,m,m},  {m,1,5,m,m},  {m,m,m,-3,m}};    int d[n]={0,m,m,m,m};  do{   for(int i=0;i<n;i++){    for(int j=0;j<n;j++){        if(A[i][j]!=m) {            if(d[j]>d[i]+A[i][j])            d[j]=d[i]+A[i][j];           }       }   }   t++;}while(t<=n-1);for(int i=0;i<n;i++){    printf("%d ",d[i]);}}
0 0
原创粉丝点击