单源点最短路径Dijkstra和Bellmanford

单源点最短路径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]);
}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值