Dijkstra算法(邻接矩阵存储)

首先我们需要熟悉Dijkstra算法的原理:

某个源点到其余各顶点的最短路径,即单源点最短路径。单源点最短路径是指:给定带权有向图G和源点v,求从v到G中其余各顶点的最短路径。迪杰斯特拉(Dijkstra)提出了按路径长度递增的顺序产生各顶点的最短路径算法。 

该算法的基本思想是: 

(1)设置两个顶点的集合S和T=V-S,集合S中存放已找到最短路径的顶点,集合T存放当前还未找到最短路径的顶点; 

(2)初始状态时,集合S中只包含源点v0; 

(3)从集合T中选取到某个顶点vi(要求vi到v0的路径长度最小)加入到S中; 

(4)S中每加入一个顶点vi,都要修改顶点v0到T中剩余顶点的最短路径长度值,它们的值为原来值与新值的较小者,新值是vi的最短路径长度加上vi到该顶点的路径长度; 

(5)不断重复(3)和(4),直到S包含全部顶点。

算法的代码实现很巧妙:

1.首先函数里面运用数组D[n]表示源点到节点n的最短距离,s[n]表示某一节点n是否已经进入集合S,如果进入则将s[i]置为1.P[n]表示当前节点n的前驱节点(用来输出路径)。

2.在开始遍历之前,首先给数组D[n]赋值为源点到该点的距离,这样便能第一次找到源点到相邻节点的最短距离(D[i]=C[v1][i];)。

3.下面找出最短距离:

if((!S[j])&&(D[j]<min))
{
min=D[j];
k=j;
}

4.更新各节点的最短距离:

for(j=0;j<n;j++)
{
if((!S[j])&&(D[j]>D[k]+C[k][j]))//调整各节点(未进入集合S)的距离值
{
D[j]=D[k]+C[k][j]; //修改蓝点j+1的距离
P[j]=k+1; //k+1是j+1的前趋
}
}

4.代码实现:

  1 #include<stdio.h>
  2 #define maxsize 1000  //表示两点间不可达,距离为无穷远
  3 #define n 7  //结点的数目
  4 void dijkstra(int C[][n],int v);//求原点v到其余顶点的最短路径及其长度
  5 void main()
  6 {
  7   
  8   //对邻接矩阵进行赋值,没有直接连通的赋值为maxsize
  9   int C[n][n]=
 10   {
 11      {maxsize,13,8,maxsize,30,maxsize,32},
 12      {maxsize,maxsize,maxsize,maxsize,maxsize,9,7},
 13      {maxsize,maxsize,maxsize,5,maxsize,maxsize,maxsize},
 14      {maxsize,maxsize,maxsize,maxsize,6,maxsize,maxsize},
 15      {maxsize,maxsize,maxsize,maxsize,maxsize,2,maxsize},
 16      {maxsize,maxsize,maxsize,maxsize,maxsize,maxsize,17},
 17      {maxsize,maxsize,maxsize,maxsize,maxsize,maxsize,maxsize}
 18   },v=1,i,j;
 19  
 20  dijkstra(C,v);//迪杰斯特拉算法
 21  
 22 }
 23 void dijkstra(int C[][n],int v)//求原点v到其余顶点的最短路径及其长度
 24 {
 25  
 26  
 27  int D[n];//用来存储从起点到某一节点的最短距离
 28  int P[n],S[n];//p[n]表示某一节点的父亲,s[n]相当于标志数组
 29  int i,j,k,v1,pre;
 30  int min,max=maxsize,inf=1200;
 31  v1=v-1;//节点号和存储的数目差1
 32  
 33  
 34  
 35  for(i=0;i<n;i++)
 36  {
 37   D[i]=C[v1][i];   //置初始距离值
 38   if(D[i]!=max) //说明存在边
 39    P[i]=v;//把父亲置为v
 40   else
 41    P[i]=0;//否则父亲置为0
 42  }
 43  
 44  
 45  
 46  for(i=0;i<n;i++)
 47   S[i]=0;      //如果某点i被访问则把该点值置为1,否则为0
 48   
 49   
 50   
 51  S[v1]=1;//已经被访问置为1
 52  D[v1]=0;    //源点v送S
 53  
 54  
 55  
 56  for(i=0;i<n-1;i++)   //扩充红点集
 57  {
 58   
 59   
 60     min=inf;//令inf>max,保证距离值为max的蓝点能扩充到S中
 61     for(j=0;j<n;j++)//在当前蓝点中选距离值最小的点k+1
 62     {
 63       if((!S[j])&&(D[j]<min))
 64       {
 65         min=D[j];//找从起点开始的最小权值
 66         k=j;
 67       }
 68     }
 69     
 70   
 71    S[k]=1;    //已经被访问,置为1
 72   
 73   
 74   for(j=0;j<n;j++)
 75   {
 76     if((!S[j])&&(D[j]>D[k]+C[k][j]))//调整各蓝点的距离值
 77     {
 78        D[j]=D[k]+C[k][j];  //修改蓝点j+1的距离
 79        P[j]=k+1;     //k+1是j+1的前趋
 80     }
 81   }
 82   
 83   
 84  }  //所有顶点均已扩充到S中
 85  
 86  
 87  for(i=0;i<n;i++)//输出结果和最短路径
 88  {
 89   printf("%d到%d的最短距离为",v,i+1);
 90   printf("%d\n",D[i]);  //打印结果
 91   pre=P[i];
 92   printf("路径:%d",i+1);
 93   while(pre!=0)  //继续找前趋顶点
 94   {
 95    printf("<——%d",pre);
 96    pre=P[pre-1];
 97   }
 98   printf("\n");
 99  }
100  
101  
102 }  

 

posted @ 2014-07-29 17:17  future_hero  阅读(4966)  评论(0编辑  收藏  举报