迪杰斯特拉算法

来源:互联网 发布:大韩火花机怎么编程 编辑:程序博客网 时间:2024/05/21 19:38

复习数据结构时,发现这个算法有点意思,就简单描述一下。

1.算法思想

迪杰斯特拉算法是用于去一点到途中其他点之间最短路径的算法。是图这一数据结构中相当重要的算法,他的主要特点是以起始点为中心,层层向外扩展,对一个节点应用迪杰斯特拉算法只能算出这个节点到图中其他节点之间的最短路径,最终能形成一条从起始节点开始到串联图中所有节点的路径。

下面进行这个算法实现的文字描述,这个算法实行采用的数据结构是图的邻接矩阵的存储结构。这个算法主要依赖于三个数组,path[ ]、dist[ ]、set[ ]三个数组。

path[ ]数组存储的是最终的最短路径中当前节点的额前去节点。

dist[ ]数组表示起始节点到当前节点的最短路径长度。

set[ ]数组表示的是当前节点是否已经在最短路径中,如果在,则设为1,反之,设为0。

实现步骤:

(1)

对三个数组进行初始化,set数组的所有元素出起始节点外,全部设为未访问,即0,起始节点的set值设为1,表示已经访问过。

dist数组,起始节点到当前节点有直接相连的路径的,dist值设为路径值,没有直接路径的,值设为无穷大。

path数组,也是根据路径来初始化,起始节点到当前节点有直接路径的,则那些节点的path值设为起始节点的节点标号。没有直接路径的,path值设为-1,代表没有直接前驱。

(2)

初始化完成后,先从dist数组中找出路径值最小的一个,让该值对应的节点标号进入最短路径中,即设置该节点的set值为1,设置该节点的path值为起始节点v。

(3)

然后是最核心的部分,更新dist数组的值和path数组的值。将起始节点通过新进入的节点到期其余各节点的路径值,与dist数组对应的节点的路径值进行比较。如果比原dist数组中的值更短,则,将更短的值付给dist数组的对应值。然后更新path数组的值,将变化的dist的节点对应的path的值更新为新进入最短路径的节点标号。最终,等到所有的节点都进入到最短路径中,则算法执行完毕。最终得出的path数组的值,便是每个最短路径中的前驱节点。

(4)

输出最短路径。利用栈,将path数组的值倒着输出。

2.算法代码实现(C++)

 

<span style="font-size:14px;"><strong>void Dijkstra(Mgraph g,int v,int dist[],int path[]){int set[maxSize];int min,i,j,k;</strong></span>
<span style="font-size:14px;"><strong><span style="color:#cc0000;">//开始初始化</span>for(i=1;i<=g.n;++i){dist[i] = g.edges[v][i];set[i] = 0;if(g.edges[v][i] < INF)path[i] = v;elsepath[i] = -1;}</strong></span>
<span style="font-size:14px;"><strong><span style="color:#cc0000;">//访问起始节点</span>set[v] = 1;path[v] = -1;<span style="color:#cc0000;">//初始化结束,开始关键操作</span>for(i = 1;i<=g.n;++i){</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>min = INF;</strong></span>
<span style="font-size:14px;"><span style="white-space:pre"></span><span style="background-color: rgb(255, 255, 255);"><span style="color:#cc0000;"><strong>//这个循环每次从其余定点中选出一个进去最短路径中。</strong></span></span></span>
<span style="font-size:14px;"><span style="white-space: pre;"></span><strong>for(j = 1;<= g.n; ++j)</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>{</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>if(set[j]==0 && dist[j]<INF){</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>min = dist[j];</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>k = j;</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>}</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>}</strong></span>
<pre name="code" class="cpp" style="font-size:14px;"><span style="font-size:14px;"><strong><span style="white-space:pre"></span>set[k] = 1;</strong></span>
<span style="font-size: 14px; white-space: pre;"></span><span style="font-size:14px;color:#cc0000;"><strong>//这个循环用于更新dist数组</strong></span>
<span style="font-size:14px;"><span style="white-space:pre"></span><strong>for(j = 1; j <= g.n; ++j)</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>{<span style="white-space:pre"></span></strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>if(set[j]==0 && (dist[k] + g.edges[k][j] < dist[j])){</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>dist[j] = dist[k] + g.edges[k][j];</strong></span>
<span style="font-size:14px;"><strong><span style="white-space:pre"></span>path[j] = k;</strong></span>
<span style="font-size: 14px;"><strong><span style="white-space:pre"></span>}</strong></span>
<span style="font-size: 14px;"><strong><span style="white-space:pre"></span>}</strong></span>
}

3.算法的时间复杂度分析

本算法的主要部分为一个双重循环,外层循环内部有两个并列的单层循环,可以任取一个循环内的操作位基本操作,所以,算法的时间复杂度为O(n*n),由此可以看出,本算法的时间复杂度只与节点的个数有关,与边的个数无关,适用于节点个数少的图中。

0 0
原创粉丝点击