dijkstra算法

dijkstra算法比较容易理解,但是代码有点复杂。

 

 

求从源点到其余各点的最短路径的算法的基本思想:

 

其中,从源点到顶点v的最短路径是所有最短短路径中长度最短者。

 

路径长度最短的最短路径的特点:

在这条路径上,必定只含一条弧,并且这条弧的权值最小。

 

下一条路径长度次短的最短路径的特点:

它只可能有两种情况:或者是直接从源点到该点(只含一条弧); 或者是,从源点经过顶点v1,再到达该顶点(由两条弧组成)。

 

再下一条路径长度次短的最短路径的特点:

它可能有三种情况:或者是,直接从源点到该点(只含一条弧); 或者是,从源点经过顶点v1,再到达该顶点(由两条弧组成);或者是,从源点经过顶点v2,再到达该顶点

 

其余最短路径的特点:

它或者是直接从源点到该点(只含一条弧); 或者是,从源点经过已求得最短路径的顶点,再到达该顶点

 

试用范围:

1.dijkstra算法实现单源最短路径查找,路径查找
2.有向图和无向图都可以使用本算法,无向图中的每条边可以看成相反的两条边。
3.用来求最短路的图中不能存在负权边。

 

具体实现请看算法,下图为简单测试图例

 

 

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 const int MAXNUM=101;
 5 
 6 int MAP[MAXNUM][MAXNUM]={
 7     {INT_MAX,      2,INT_MAX,INT_MAX,INT_MAX,      9,     15,INT_MAX,INT_MAX},
 8     {INT_MAX,INT_MAX,      4,INT_MAX,INT_MAX,INT_MAX,      6,INT_MAX,INT_MAX},
 9     {INT_MAX,INT_MAX,INT_MAX,      2,INT_MAX,INT_MAX,INT_MAX,INT_MAX,     15},
10     {INT_MAX,INT_MAX,INT_MAX,INT_MAX,      1,INT_MAX,INT_MAX,INT_MAX,      1},
11     {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,      6,INT_MAX,      3,INT_MAX},
12     {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,     11,INT_MAX},
13     {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,     15,      2},
14     {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,      4},
15     {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX}
16 };
17 
18 int dist[MAXNUM];    //存储s到各点的最短路径
19 int path[MAXNUM];    //存储s到各点的最短路径中的倒数第二个结点
20 
21 #define MAXSUM(a,b) ( ((a)!=INT_MAX&&(b)!=INT_MAX) ? ((a)+(b)) : INT_MAX )
22 
23 void dijkstra(int s,int n)
24 {
25     bool mark[MAXNUM]={false};    //标记s到i是否属于最短路径范畴
26     mark[s]=true;    //标记源点s不属于搜索范围
27     int i;
28     for(i=0;i<n;++i)
29     {
30         dist[i]=MAP[s][i]; //初始化s到各点的长度
31         path[i]=s;    //path初始化为s,既s为到各结点的路径的倒数第二个结点
32     }
33     for(i=2;i<n;++i)    //循环n-2次就可以找出n-1条最短路径
34     {
35         int index=s,lowcost=INT_MAX;
36         int j;
37 
38         //在不是最短路径的路径中(mark[j]==false),找出一条最小的路径,
39         //并标记为最新的最短路径(mark[index]=true)
40         for(j=0;j<n;++j)
41             if(mark[j]==false&&dist[j]<lowcost)
42             {
43                 index=j;
44                 lowcost=dist[j];
45             }
46         mark[index]=true;
47         //用最新的最短路径更新剩下的非最短路径
48         //既mark[j]==false的路径
49         for(j=0;j<n;++j)
50             if(mark[j]==false&&MAXSUM(dist[index],MAP[index][j])<dist[j])
51             {
52                 //dist[j]=min{dist[j],dist[index]+MAP[index][j]}
53                 dist[j]=MAXSUM(dist[index],MAP[index][j]);
54                 //确定要更新时,同时更新新路径的倒数第二个结点
55                 path[j]=index;    
56             }
57     }
58 }
59 
60 void reverse(int a[],int n)
61 {
62     for(int i=0,j=n-1;i<j;++i,--j)
63         swap(a[i],a[j]);
64 }
65 
66 int getpath(int a[],int s,int i)
67 {
68     int count=1;
69     a[0]=i;
70     while(i!=s)
71     {
72         //path[i]存储s到i路径中i的前驱结点
73         i=a[count++]=path[i];
74     }
75     reverse(a,count);
76     return count;
77 }
78 
79 int main()
80 {
81     int a[MAXNUM];
82     for(int k=0;k<9;++k)
83     {
84         dijkstra(k,9);
85         for(int i=0;i<9;++i)
86             if(dist[i]!=INT_MAX)
87             {
88                 cout<<char(k+'a')<<""<<char(i+'a')<<"最短路径长度为:";
89                 cout<<dist[i]<<endl;
90                 int length=getpath(a,k,i);
91                 for(int j=0;j<length;++j)
92                     cout<<char(a[j]+'a')<<' ';
93                 cout<<endl<<endl;
94             }
95     }
96     return 0;
97 }

 

 

 

 

dijkstra算法还有另一种实现,利用队列进行优先级管理,时间复杂度为O((n-2)(n-1)/2),上面dijkstra算法实现的时间复杂度为O((n-2)(n-1)),很明显下面的实现效率是上面的两倍

 1 void dijkstra(int s,int n)
 2 {
 3     int q[MAXNUM],qf=0,ql=0;    //建立一个队列
 4     int i;
 5     for(i=0;i<n;++i)    //初始化dis,path,q
 6     {
 7         dist[i]=MAP[s][i];
 8         path[i]=s;        //path初始化为s,既s为到各结点的路径的倒数第二个结点
 9         if(i!=s)    //将非源点的结点的下标均放进队列
10             q[ql++]=i;    
11     }
12     while(qf<ql-1)        //循环n-2次就可以完成
13     {
14         //找出dist[q[qf~ql-1]]最小者,并记录队列q的下标
15         int index_min=qf;
16         for(i=qf+1;i<ql;++i)
17             if(dist[q[i]]<dist[q[index_min]])
18                 index_min=i;
19         swap(q[index_min],q[qf]);//保持q[qf]指向最短的,既确定最新的最短路径
20         //如果找出的最短路径是无路径的,那后面的循环毫无意义,可直接跳出
21         if(dist[q[qf]]==INT_MAX)
22             break;
23         //用最新的最短路径dist[q[qf]]来更新dist[q[qf+1~ql-1]]
24         //主意q[qf+1~ql-1]均指向非最短路径的路径
25         for(i=qf+1;i<ql;++i)
26             if(MAXSUM(dist[q[qf]],MAP[q[qf]][q[i]])<dist[q[i]])
27             {
28                 dist[q[i]]=MAXSUM(dist[q[qf]],MAP[q[qf]][q[i]]);
29                 path[q[i]]=q[qf];
30             }
31         ++qf;
32     }
33 }

 

 

posted on 2011-02-01 00:05  bug睡的略爽  阅读(262)  评论(0编辑  收藏  举报

导航