网络最短路问题的改进算法

 第23卷第9期  2002年9月

文章编号:1000-1220(2002) 09-1083-05

小型微型计算机系统M IN I -M I CRO SY ST EM V ol. 23N o. 9  Sep . 2002  

网络最短路问题的改进算法

王晓东 陈国龙 林柏钢

(福州大学计算机科学与技术系, 福建福州350002)

摘 要:本文着重研究著名的Dijkstr a 网络最短路算法的实现效率, 提出算法实现的若干技巧, 大大提高了Dijkstra 最

短路算法的适用性和时间空间效率.

关键词:网络; 最短路; Dijkst ra 算法; 算法效率. 中图分类号:T P 311     文献标识码:A

1 引 言

网络最短路问题是网络优化领域中最常见的基本问题之一. 许多网络优化问题都以最短路问题为其子问题. 因此, 在网络的实际应用中, 最短路算法的效率显得越来越重要, 受到国内外学者的普遍关注. 本文着重研究著名的Dijkstr a 最短路算法的实现效率, 提出算法实现的若干技巧, 大大提高了Dijkstra 最短路算法的适用性和时间空间效率.

一个网络N 是一个赋权有向图G=(V , E) , 其中每一条边(u , v ) ∈E 都有一边权c (u , v ) ∈R . 网络最短路问题所关心的是求网络中一给定顶点s ∈V (称为源) 到网络中所有其他顶点间的最短路. 这里所说的路的长度是指路上各边权的和. 迄今为止大多数的网络最短路算法可纳入下面的算法框架

〔4〕

络N 是一个非负网络, 即对任意(u, v ) ∈E 有c 〔u, v 〕≥0时,

如果我们让Selec t(U ) 从当前标号顶点集U 中选取当前路长D 最短的顶点u , 即D (u ) =min {D (v ) |v ∈U }, 我们就得到著名的Dijkstra 最短路算法.

本文中设|V |=n , |E |=m . 如果用堆来存储标号顶点集U , 则Dijkst ra 最短路算法所需的计算时间为O (m log n ) 〔1〕. 下面我们要讨论当边权为非负整数时, 对Dijkstra 最短路算法的时间和W 空间效率的改进.

2 桶算法设计

设网络N 各边的权值为0到C-1之间的整数, C 为一正整数.

注意到Dijkst ra 算法的关键在于从当前标号顶点集U 中选取当前路长D 最短的顶点u , 即D (u )=min {D (v ) |v ∈U }.而对任意u, v ∈U , 且D 〔u 〕

〔v 〕

〔w 〕+c (w , v ) ≤D 〔u 〕+C-1. 换句话说, 在任一时刻, U 中顶

点最多有C 个不同的D 值. 即在任一时刻, 总存在常数a , 使得对任意v ∈U 有a ≤D 〔v 〕≤a +C-1.

由此我们想到可以用桶排序算法的思想, 设置若干个桶来存放U 中的元素, 使得当v ∈U 时, 将顶点v 存放在D 〔v 〕号桶中. 显然, 在任何时刻对任意v ∈V , 从源s 到v 的当前最短路长D (v ) 有0≤D (v ) ≤(n -1) (C -1). 因此在最坏情况下需要O (nC ) 的桶空间. 由于在任一时刻, U 中顶点最多有C 个不同的D 值, 我们可以将所需的桶空间从O (nC) 减少到只需要C 个桶. 这里可能遇到的一个问题是, 在算法执行过程中, a 值可能不断增大. 为了解决这个问题, 我们可以设置一个游标k 指示出当前最小桶编号的位置. U 中元素最多存放在其后的C -1个桶中. 当顺序的C 个桶超出桶头数组的界时, 可用循环数组的思想再从头开始存放. 桶中顶点可用一个循环链表来存储. 由于在每个桶中存入一个顶点需要O (1) 时间. 算法Select 除了对链表的处理时间外, 还需要O (C) 计算时间. 因为在整个算法中E 的每条边处理一次, 故算法对链表

.

Begin

Proced ure Sh ortes tPath s(V, E, c, s );

 D 〔s 〕:=0; U :={s};

≠s ) Do D 〔u 〕:=+∞; Fo r (u

W hile (U ≠Υ) Do   Begin

   u :=Select (U );

Delete (u , U ) ;

Fo r (u , v ) ∈E Do

      If (D 〔u 〕+c 〔u, v 〕

        D 〔v 〕:=D 〔u 〕+c 〔u, v 〕;

Ins ert(v, U);

       End;     End;   End;

其中集合U 是标号顶点集. Select(U ) 从当前标号顶点集U 中选取一个顶点. Delete (u , U ) 将顶点u 从当前标号顶点集U 中删去. Inser t (v , U ) 将顶点v 插入当前标号顶点集U 中.

Selec t(U ) 的不同实现方式导致不同的最短路算法. 当网

  收稿日期:2001-03-12 基金项目:国家(973G 1998030600T ) 项目资助; 福建省科技厅杰出人才基金项目(2000Z 148) 资助.  作者简介:王晓东, 教授, 研究领域为数据结构, 算法设计与分析.

         1084

小 型 微 型 计 算 机 系 统       2002年

处理所需的总时间为O (m ). 由此可知上述Dijkstra 最短路桶算法需要O (m+Cn) 计算时间和O (m +n +C) 空间〔1, 2〕.

我们注意到, 当网络N 中各边权的最大值C 不太大时, 上述O (m+Cn) 计算时间的桶算法是对O (m log n ) 〔1〕时间Di-jkstr a 最短路算法的改进. 而当C 值较大时桶算法的效率明显降低. 更严重的是在实际计算时的空间需求得不到满足, 导致计算失败. 鉴于这种情况, 我们提出对上述最短路桶算法的2个改进算法, 进一步降低算法的时空需求.

3 算法的改进

3. 1 桶空间压缩算法

在最短路桶算法中, 每个桶中存储的顶点具有相同的最短路长. 在一般情况下, 每个桶中只有少量的顶点, 甚至有许多空桶. 为了节省桶空间, 提高算法效率, 我们将连续的桶空间均匀地划分为[C /L]段, 每段中的L 个桶合并为一个桶, 如图1所示

.

图1 桶空间压缩

  在合并后的桶中, 所有桶中顶点按先进先出的原则组织成队列, 依据Sho rtest Paths 所给的算法框架进行计算. 下面我们根据上述思想来描述桶压缩算法的数据结构及其算法实现策略.

首先采用紧凑邻接表来表示给定的网络N , 即将通常表示网络的邻接表的顶点表数组中各顶点所相应的边表用一个边表数组紧凑地存储〔3〕. 其中顶点和边的数据类型node 和ar c 说明如下.

Type

nodeP =↑node; arcP=↑arc; node=

R ecord

  firs t , dis t , index :Longin t;

parent , next , prev :nodeP; status :Integer; End; arc =

Reco rd

  len , head :Longint;   End;

〕Of nodeP ; buck et =Array 〔0. . M AXLENGT H BucketHeap =

Record

size , base, curr , low :Longint; firs t:buck et; End;

其中size 表示桶数组的大小; base 表示当前路长基数;

cur r 表示当前桶数组中最短路长所对应的桶号; low 表示当前桶数组中循环存储部分最小桶号; first 是当前桶数组.

采用所述数据结构的桶空间压缩算法可描述如下.

Procedure BucketSP ;

Begin

 InitHeap ; {桶初始化}W hile (T ru e) Do

   Begin

   DeleteM in (nodefrom ); {从桶中取出当前最短距离顶点

nodefrom }

If (n od efrom =Nil ) Th en Exit ;

las t :=nod es 〔nod efrom ↑. index+1〕↑. firs t-1; dis tfrom:=n od efrom ↑. dis t; {检查从nodefrom 发出的每一条边}For j :=nodefrom ↑. firs t To las t Do

     Begin

      nodeto :=nod es 〔arcs 〔〕〕; {nod eto 为当前边j ↑. h ead

所指向的顶点}

dis tnew:=dis tfrom +(arcs 〔j 〕↑. len) ; If (distnew

     Begin

      BucketPos (dis tnew , pos new ); {计算出应存入的桶号

posnew }

ins :=true;

If ((nod eto ↑. s tatus =0) ) Th en {顶点nodeto 已在桶

中}

      Begin

       dis told :=nodeto ↑. dist;

);

表示网络N 紧凑邻接表的顶点表数组nodes 和边表数

组a rcs 说明为:

nodes :Array 〔0. . M AXN 〕Of n od eP ; :Ar ray 〔0. . M AXM 〕Of arcP ; arcs

在第i 个顶点记录中, first 表示顶点i 的第一条出边在边表数组a rcs 中的位置; dist 表示顶点i 的当前最短距离; index

表示顶点i 在顶点表数组nodes 中的位置; par ent 表示顶点i 在当前最短路中的父顶点的编号; nex t 和pr ev 分别是指向顶点i 在桶链表中的下一个顶点和前一个顶点的指针; status 是表示顶点i 是否属于集合U 的标志变量.

在第i 条边的记录中, le n 表示该边的边长; head 表示该边所指向的顶点编号.

:

9期       

If (posold posn ew ) :=false ; Else ins

      End;

王晓东等:网络最短路问题的改进算法

Then R emove (nodeto ,

   BHeap . low :=pos ;

 End ;

  

1085

pos old) {将顶点nodeto 从桶中删去}

     If (ins)Th en Ins ert(nodeto, pos new ); {将顶点nodeto 存

入桶posnew }

nod eto ↑. dist :=distnew; nod eto ↑. parent :=nodefrom;

     End;     End ;    End;  End ;

算法Delete Min(u) 实现网络最短路算法框架中u :=Se-lect (U ) 和Dele te(u, U ) 这2个计算步骤, 并在计算中调整桶中数据分布.

Procedure DeleteMin (var node :nodeP );  Label rep;  Begin   rep :

   {找最小非空桶}

W hile ((B Heap . cu rr

    BHeap. curr :=B Heap. cu rr +1;    If (BHeap. curr=B Heap. size) Th en     Begin

     If (BHeap. low

       B Heap . curr :=B Heap . low ;

B Heap . low :=B Heap . size ; B Heap. base :=BHeap. bas e +B Heap. size *L; Goto rep;

      End

     Else node :=Nil;     End

   Else {curr 为最小非空桶号}    Begin

     node :=BHeap . first 〔B Heap . cu rr 〕; node ↑. statu s :=1;

If (nod e ↑. nex t=nod e) Th en{桶中仅有一个顶点}

     BHeap. firs t 〔BHeap. curr 〕:=Nil     Else      Begin

      node ↑. prev ↑. next :=node ↑. n ext;

node ↑. nex t ↑. p rev :=node ↑. p rev ;

〕:=node ↑. nex t ; B Heap . firs 〔t BHeap . curr

     End ;    End; End;

其中Bucket Pos(dista nce, po s) 根据当前顶点的最短路长distance 计算出其应存入的桶号pos, 算法描述如下.

Procedure BucketPos (distance :longint ; var pos :longint );

begin

  pos :=dis tance-B Heap. base;

:=pos DIV L ; pos

if pos>=BHeap. size then pos :=pos-B Heap. size els e if pos

  End;

算法Remov e (node , pos ) 将顶点node 从桶pos 中删去.

Procedure Remove (node :nodeP ; pos :longint );

Begin

 If (node ↑. n ext =node ) Then BHeap . firs t 〔pos 〕:=Nil Els e

   Begin

    node ↑. p rev ↑. nex t :=node ↑. nex t;

node ↑. next ↑. prev:=node ↑. prev; If (BHeap. first 〔pos 〕=node) Then

     BHeap. firs t 〔pos 〕:=node ↑. nex t ;    End ;   End;

算法Inser t (node, po s) 将顶点node 存入桶po s 中.

Procedure Insert (node :nodeP ; pos :longint );  var tem p :nod eP ;  Begin

  If (B Heap. first 〔pos 〕=Nil) Then    Begin

    BHeap. firs t 〔pos 〕:=node;

node ↑. next :=node; node ↑. p rev:=node;

   End   Els e    Begin     temp :=B Heap . firs t 〔pos 〕;

↑. prev ↑. nex t :=node ; temp

node ↑. p rev:=temp ↑. p rev; node ↑. next :=temp; temp ↑. prev:=node;

   End;

  node ↑. s tatus :=0;

If () 3. 2 桶空间截断算法

桶空间截断算法的基本思想是预先设置桶数组长度L. 在桶号为0~L -1所表示的距离范围内, 按照通常的办法来存储顶点. 而将当前最短路长超过0~L-1号桶所表示的距离范围的顶点存入L 号桶. 在算法中不断执行DeleteM in 运算, 一旦出现0~L-1号桶均为空桶时, 将L 号桶中顶点重新分布到0~L-1号桶中.

Procedure DeleteMin (var node :nodeP );  var bound, dis tn ew , posnew:longin t;    h ead, tail, nex tnode :nodeP;  Label rep;  Begin   rep :

   {找最小非空桶}

W hile ((BHeap. cur r

〔B Heap. cu rr 〕=Nil) ) Do

=1;

         1086

小 型 微 型 计 算 机 系 统

   BHeap . firs t 〔BHeap . curr 〕:=Nil

  Else    Begin

       2002年

   If (BHeap . cu rr =BHeap . s ize ) Then {0~L -1号桶均为空桶}    Begin

     If (BHeap . firs t 〔BHeap . size 〕Nil ) Th en {L 号桶非空}      Begin

       nod e :=B Heap . firs t 〔B Heap . size 〕;

↑. prev ↑. nex :nod e t =Nil ; {断开为非循环双链表}

:=BIG ; BHeap . bas e

w hile (node NIl ) do {计算新路长基数}

      Begin

       If node ↑. dis t

node ↑. dis t ; node :=node ↑. n ext ;

      End ;

     bound :=B Heap. base +BHeap. size; {顶点分布上界}

:=0; BHeap . cur r

tail :=Nil ; h ead :=Nil;

nod e :=B Heap. firs t 〔B Heap. size 〕;

~L -while (node NIl ) do {L 号桶中顶点重新分布到0

1号桶中}

      Begin

       nex tnode :=node ↑. next ;

distnew:=node ↑. dis t ;

If (distnew

        Begin

         BucketPos (distnew, pos new );

Ins ert(node, posnew );

        End

       Else{保留在L 号桶中}        Begin

         If (tail Nil) Then           Begin

           tail ↑. next :=node;

nod e ↑. prev:=tail;

          End

         Else h ead :=node;

tail :=node;

       End;

      nod e :=nextnode;      End;

    If (tail Nil) Then{置为循环链表}      Begin

       tail ↑. next :=head;

h ead ↑. prev:=tail ;

      End;

     BHeap. firs t 〔BHeap. size 〕:=h ead;

Goto rep;

    End

   Els e node :=Nil; {U= }  End

 Els e{cu rr 为最小非空桶号}  Begin

   node :=B Heap. firs t 〔BHeap. curr 〕;

node ↑. s tatus :=1;

  If . n     node ↑. prev ↑. n ext :=node ↑. nex t;

node ↑. nex t ↑. p rev :=node ↑. prev; BHeap. firs t 〔BHeap. curr 〕:=node ↑. nex t;

   End;   End; End;

由于数据结构的改变, 桶中顶点不需要循环存储, 根据当

前顶点的最短路长dista nce 计算出其应存入的桶号pos 的算法Bucket Po s (distance , pos ) 作相应调整如下.

:longint ; var pos :longint ); Procedure BucketPos (distance

 b egin

  pos :=distance-BHeap. bas e;

if pos >B Heap. size th en pos :=BHeap. size els e if pos

由此可设计出网络最短路的桶空间截断算法.

4 算法复杂性分析

4. 1 桶空间压缩算法的计算复杂性

桶空间压缩算法需要[C /L]个桶, 桶中每个顶点需要O (1) 存储空间. 除了紧凑邻接表所需要的O (m +n ) 空间外, 尚需O (n +C /L) 的存储空间. 因此桶空间压缩算法所需的存储空间为O (m +n +C /L ).

由于在桶空间压缩算法中, 每个桶中顶点是按照队列组织存放的, 所以一个顶点可能多次进出同一桶顶点队列. 而当同一顶点重复进入桶顶点队列时, 其当前最短距离至少减1. 因此同一顶点进入同一桶顶点队列的次数不超过L 次. 每个顶点进出队列一次所需的处理时间为O (1) , 每一条边所需的处理时间也是O (1) , 由此可见, 对桶中所有顶点进行处理所需的时间是O (L(m+n) ). 另一方面, 算法DeleteM in 的搜索非空桶的W hile 循环体需要O (C /L ) 计算时间, 而循环体最多被执行n 次, 因此算法中搜索非空桶所需的总时间为O (nC /L ).

综上可知, 桶空间压缩算法所需的计算时间为O (m L+n (L +C /L ) ). 4. 2 桶空间截断算法的计算复杂性

桶空间截断算法所需的空间显然为O (L +n ). 在桶空间截断算法中, 第0~L-1号桶中顶点的组织方式与桶算法完全一致. 桶中每个顶点恰被处理一次. 因此对桶中所有顶点进行处理所需的总时间为O (m +n). 桶空间截断算法与桶算法的主要区别在于截断的第L 号桶中顶点的重新分布. 在每一次作顶点重新分布时, 插入到0~L-1号桶中顶点所需的处理时间可用簿记的方法来计算. 每个顶点插入到每个桶中至多一次, 总共有L 个桶, 故所需的计算时间为O (nL). 另外, 在每一次重新分布后保留在第L 号桶中的顶点所需的处理时间也可用簿记的方法来计算. 每一次重新分布L 号L , L 号

9期       王晓东等:网络最短路问题的改进算法  

1087

多重新分布C /L 次. 每一次重新分布扫描一个顶点所需时间为O (1) , 因此保留在第L 号桶中顶点所需的处理时间为O (nC /L ).

综上可知, 桶空间截断算法所需的计算时间为O (m+n (L +C /L ) ).

在用桶空间压缩算法和桶空间截断算法且边权变化范围较大时取L =

U . 实际计算的结果如表2所示. 表2 大范围变边权实验结果

边权变化区间〔1. . 1〕〔0. . 10〕〔0. . 100〕〔0. . 10000〕〔0. . 1000000〕

桶算法1. 54. 129. 0323. 17内存溢出

桶空间压缩算法

2. 713. 884. 665. 806. 23

桶空间截断算法

1. 772. 072. 182. 233. 20

5 算法实验比较分析

对于网络最短路的桶算法和本文提出的桶空间压缩算法和桶空间截断算法从常规小边权和大范围变边权2个方面进行了实验比较, 所得的实验结果与理论分析完全一致. 5. 1 常规小边权实验结果对于边权在〔0…10〕范围内随机生成的非负网络用上述3个算法实际计算的结果如表1所示.

表1 常规小边权实验结果

结点数/边数桶算法桶空间压缩算法

512/655360. 090. 021024/262144

0. 46

0. 110. 481. 95

2048/10485761. 974096/41943048. 37

桶空间截断算法

0. 02

0. 120. 492. 02

表中所列计算时间为秒. 测试所用机型为P Ⅲ850, 128M 内存.

从上述实验结果可以看出, 当边权变化范围较大时, 桶空间压缩算法和桶空间截断算法均明显优于桶算法. 桶空间截断算法略优于桶空间压缩算法.

参 考 文 献

1Cormen T. H. , Leis ers on C. E. , R iv es t R. L. . Introduction to 〔M 〕. M IT Press , Camb ridg e , M A , 1990. 429~433algo rith ms

2Dial R . B. . Algo rith m 360:sho rtest path fores t w ith topological ordering 〔J 〕. Comm. ACM 12, 1969. 632~633

3Sahni S . . Data s tructures , algorithms , and applications in C ++〔M 〕. M cGraw Hill, New Yo rk , 1998. 569~570

4W ang Xiao -d ong . Th e d esing and analysis of comp uter algo rith ms 〔M 〕. Beijing :Publish ing House of Electronics Ind ustry. 2001(王晓东. 计算机算法设计与分析〔M 〕. 北京, 电子工业出版社. 2001. 94~96)

  表中所列计算时间为秒. 测试所用机型为P Ⅲ850, 128M

内存.

从上述实验结果可以看出, 对于常规小边权, 桶空间压缩算法和桶空间截断算法均优于桶算法. 桶空间压缩算法和桶空间截断算法之间的差别不大.

5. 2 大范围变边权实验结果

对于130000个结点和500000条且边权在〔L . . U 〕范围内随机变化的非负网络对上述3个算法进行实际计算比较.

Improved Algorithms for Network Shortest Paths Problem

W AN G Xia o-do ng , CHEN Guo-lo ng , L IN Bo-ga ng

(Computer Science Depar tment of F uzhou University , Fuz hou 350002, Ch ina )

Abstract  This paper discusses the desig n and im plementatio n strategies of the famo us Dijkstr a sho r test paths alg o rithm. The new techniques sugg ested improv e the time and space co mplexities o f the sho r test pa th s alg orithm sig nificantly . Key words  netw o rks; sho rtest paths; dijkstr a alg o rithm; algo rithm efficie ncy

 第23卷第9期  2002年9月

文章编号:1000-1220(2002) 09-1083-05

小型微型计算机系统M IN I -M I CRO SY ST EM V ol. 23N o. 9  Sep . 2002  

网络最短路问题的改进算法

王晓东 陈国龙 林柏钢

(福州大学计算机科学与技术系, 福建福州350002)

摘 要:本文着重研究著名的Dijkstr a 网络最短路算法的实现效率, 提出算法实现的若干技巧, 大大提高了Dijkstra 最

短路算法的适用性和时间空间效率.

关键词:网络; 最短路; Dijkst ra 算法; 算法效率. 中图分类号:T P 311     文献标识码:A

1 引 言

网络最短路问题是网络优化领域中最常见的基本问题之一. 许多网络优化问题都以最短路问题为其子问题. 因此, 在网络的实际应用中, 最短路算法的效率显得越来越重要, 受到国内外学者的普遍关注. 本文着重研究著名的Dijkstr a 最短路算法的实现效率, 提出算法实现的若干技巧, 大大提高了Dijkstra 最短路算法的适用性和时间空间效率.

一个网络N 是一个赋权有向图G=(V , E) , 其中每一条边(u , v ) ∈E 都有一边权c (u , v ) ∈R . 网络最短路问题所关心的是求网络中一给定顶点s ∈V (称为源) 到网络中所有其他顶点间的最短路. 这里所说的路的长度是指路上各边权的和. 迄今为止大多数的网络最短路算法可纳入下面的算法框架

〔4〕

络N 是一个非负网络, 即对任意(u, v ) ∈E 有c 〔u, v 〕≥0时,

如果我们让Selec t(U ) 从当前标号顶点集U 中选取当前路长D 最短的顶点u , 即D (u ) =min {D (v ) |v ∈U }, 我们就得到著名的Dijkstra 最短路算法.

本文中设|V |=n , |E |=m . 如果用堆来存储标号顶点集U , 则Dijkst ra 最短路算法所需的计算时间为O (m log n ) 〔1〕. 下面我们要讨论当边权为非负整数时, 对Dijkstra 最短路算法的时间和W 空间效率的改进.

2 桶算法设计

设网络N 各边的权值为0到C-1之间的整数, C 为一正整数.

注意到Dijkst ra 算法的关键在于从当前标号顶点集U 中选取当前路长D 最短的顶点u , 即D (u )=min {D (v ) |v ∈U }.而对任意u, v ∈U , 且D 〔u 〕

〔v 〕

〔w 〕+c (w , v ) ≤D 〔u 〕+C-1. 换句话说, 在任一时刻, U 中顶

点最多有C 个不同的D 值. 即在任一时刻, 总存在常数a , 使得对任意v ∈U 有a ≤D 〔v 〕≤a +C-1.

由此我们想到可以用桶排序算法的思想, 设置若干个桶来存放U 中的元素, 使得当v ∈U 时, 将顶点v 存放在D 〔v 〕号桶中. 显然, 在任何时刻对任意v ∈V , 从源s 到v 的当前最短路长D (v ) 有0≤D (v ) ≤(n -1) (C -1). 因此在最坏情况下需要O (nC ) 的桶空间. 由于在任一时刻, U 中顶点最多有C 个不同的D 值, 我们可以将所需的桶空间从O (nC) 减少到只需要C 个桶. 这里可能遇到的一个问题是, 在算法执行过程中, a 值可能不断增大. 为了解决这个问题, 我们可以设置一个游标k 指示出当前最小桶编号的位置. U 中元素最多存放在其后的C -1个桶中. 当顺序的C 个桶超出桶头数组的界时, 可用循环数组的思想再从头开始存放. 桶中顶点可用一个循环链表来存储. 由于在每个桶中存入一个顶点需要O (1) 时间. 算法Select 除了对链表的处理时间外, 还需要O (C) 计算时间. 因为在整个算法中E 的每条边处理一次, 故算法对链表

.

Begin

Proced ure Sh ortes tPath s(V, E, c, s );

 D 〔s 〕:=0; U :={s};

≠s ) Do D 〔u 〕:=+∞; Fo r (u

W hile (U ≠Υ) Do   Begin

   u :=Select (U );

Delete (u , U ) ;

Fo r (u , v ) ∈E Do

      If (D 〔u 〕+c 〔u, v 〕

        D 〔v 〕:=D 〔u 〕+c 〔u, v 〕;

Ins ert(v, U);

       End;     End;   End;

其中集合U 是标号顶点集. Select(U ) 从当前标号顶点集U 中选取一个顶点. Delete (u , U ) 将顶点u 从当前标号顶点集U 中删去. Inser t (v , U ) 将顶点v 插入当前标号顶点集U 中.

Selec t(U ) 的不同实现方式导致不同的最短路算法. 当网

  收稿日期:2001-03-12 基金项目:国家(973G 1998030600T ) 项目资助; 福建省科技厅杰出人才基金项目(2000Z 148) 资助.  作者简介:王晓东, 教授, 研究领域为数据结构, 算法设计与分析.

         1084

小 型 微 型 计 算 机 系 统       2002年

处理所需的总时间为O (m ). 由此可知上述Dijkstra 最短路桶算法需要O (m+Cn) 计算时间和O (m +n +C) 空间〔1, 2〕.

我们注意到, 当网络N 中各边权的最大值C 不太大时, 上述O (m+Cn) 计算时间的桶算法是对O (m log n ) 〔1〕时间Di-jkstr a 最短路算法的改进. 而当C 值较大时桶算法的效率明显降低. 更严重的是在实际计算时的空间需求得不到满足, 导致计算失败. 鉴于这种情况, 我们提出对上述最短路桶算法的2个改进算法, 进一步降低算法的时空需求.

3 算法的改进

3. 1 桶空间压缩算法

在最短路桶算法中, 每个桶中存储的顶点具有相同的最短路长. 在一般情况下, 每个桶中只有少量的顶点, 甚至有许多空桶. 为了节省桶空间, 提高算法效率, 我们将连续的桶空间均匀地划分为[C /L]段, 每段中的L 个桶合并为一个桶, 如图1所示

.

图1 桶空间压缩

  在合并后的桶中, 所有桶中顶点按先进先出的原则组织成队列, 依据Sho rtest Paths 所给的算法框架进行计算. 下面我们根据上述思想来描述桶压缩算法的数据结构及其算法实现策略.

首先采用紧凑邻接表来表示给定的网络N , 即将通常表示网络的邻接表的顶点表数组中各顶点所相应的边表用一个边表数组紧凑地存储〔3〕. 其中顶点和边的数据类型node 和ar c 说明如下.

Type

nodeP =↑node; arcP=↑arc; node=

R ecord

  firs t , dis t , index :Longin t;

parent , next , prev :nodeP; status :Integer; End; arc =

Reco rd

  len , head :Longint;   End;

〕Of nodeP ; buck et =Array 〔0. . M AXLENGT H BucketHeap =

Record

size , base, curr , low :Longint; firs t:buck et; End;

其中size 表示桶数组的大小; base 表示当前路长基数;

cur r 表示当前桶数组中最短路长所对应的桶号; low 表示当前桶数组中循环存储部分最小桶号; first 是当前桶数组.

采用所述数据结构的桶空间压缩算法可描述如下.

Procedure BucketSP ;

Begin

 InitHeap ; {桶初始化}W hile (T ru e) Do

   Begin

   DeleteM in (nodefrom ); {从桶中取出当前最短距离顶点

nodefrom }

If (n od efrom =Nil ) Th en Exit ;

las t :=nod es 〔nod efrom ↑. index+1〕↑. firs t-1; dis tfrom:=n od efrom ↑. dis t; {检查从nodefrom 发出的每一条边}For j :=nodefrom ↑. firs t To las t Do

     Begin

      nodeto :=nod es 〔arcs 〔〕〕; {nod eto 为当前边j ↑. h ead

所指向的顶点}

dis tnew:=dis tfrom +(arcs 〔j 〕↑. len) ; If (distnew

     Begin

      BucketPos (dis tnew , pos new ); {计算出应存入的桶号

posnew }

ins :=true;

If ((nod eto ↑. s tatus =0) ) Th en {顶点nodeto 已在桶

中}

      Begin

       dis told :=nodeto ↑. dist;

);

表示网络N 紧凑邻接表的顶点表数组nodes 和边表数

组a rcs 说明为:

nodes :Array 〔0. . M AXN 〕Of n od eP ; :Ar ray 〔0. . M AXM 〕Of arcP ; arcs

在第i 个顶点记录中, first 表示顶点i 的第一条出边在边表数组a rcs 中的位置; dist 表示顶点i 的当前最短距离; index

表示顶点i 在顶点表数组nodes 中的位置; par ent 表示顶点i 在当前最短路中的父顶点的编号; nex t 和pr ev 分别是指向顶点i 在桶链表中的下一个顶点和前一个顶点的指针; status 是表示顶点i 是否属于集合U 的标志变量.

在第i 条边的记录中, le n 表示该边的边长; head 表示该边所指向的顶点编号.

:

9期       

If (posold posn ew ) :=false ; Else ins

      End;

王晓东等:网络最短路问题的改进算法

Then R emove (nodeto ,

   BHeap . low :=pos ;

 End ;

  

1085

pos old) {将顶点nodeto 从桶中删去}

     If (ins)Th en Ins ert(nodeto, pos new ); {将顶点nodeto 存

入桶posnew }

nod eto ↑. dist :=distnew; nod eto ↑. parent :=nodefrom;

     End;     End ;    End;  End ;

算法Delete Min(u) 实现网络最短路算法框架中u :=Se-lect (U ) 和Dele te(u, U ) 这2个计算步骤, 并在计算中调整桶中数据分布.

Procedure DeleteMin (var node :nodeP );  Label rep;  Begin   rep :

   {找最小非空桶}

W hile ((B Heap . cu rr

    BHeap. curr :=B Heap. cu rr +1;    If (BHeap. curr=B Heap. size) Th en     Begin

     If (BHeap. low

       B Heap . curr :=B Heap . low ;

B Heap . low :=B Heap . size ; B Heap. base :=BHeap. bas e +B Heap. size *L; Goto rep;

      End

     Else node :=Nil;     End

   Else {curr 为最小非空桶号}    Begin

     node :=BHeap . first 〔B Heap . cu rr 〕; node ↑. statu s :=1;

If (nod e ↑. nex t=nod e) Th en{桶中仅有一个顶点}

     BHeap. firs t 〔BHeap. curr 〕:=Nil     Else      Begin

      node ↑. prev ↑. next :=node ↑. n ext;

node ↑. nex t ↑. p rev :=node ↑. p rev ;

〕:=node ↑. nex t ; B Heap . firs 〔t BHeap . curr

     End ;    End; End;

其中Bucket Pos(dista nce, po s) 根据当前顶点的最短路长distance 计算出其应存入的桶号pos, 算法描述如下.

Procedure BucketPos (distance :longint ; var pos :longint );

begin

  pos :=dis tance-B Heap. base;

:=pos DIV L ; pos

if pos>=BHeap. size then pos :=pos-B Heap. size els e if pos

  End;

算法Remov e (node , pos ) 将顶点node 从桶pos 中删去.

Procedure Remove (node :nodeP ; pos :longint );

Begin

 If (node ↑. n ext =node ) Then BHeap . firs t 〔pos 〕:=Nil Els e

   Begin

    node ↑. p rev ↑. nex t :=node ↑. nex t;

node ↑. next ↑. prev:=node ↑. prev; If (BHeap. first 〔pos 〕=node) Then

     BHeap. firs t 〔pos 〕:=node ↑. nex t ;    End ;   End;

算法Inser t (node, po s) 将顶点node 存入桶po s 中.

Procedure Insert (node :nodeP ; pos :longint );  var tem p :nod eP ;  Begin

  If (B Heap. first 〔pos 〕=Nil) Then    Begin

    BHeap. firs t 〔pos 〕:=node;

node ↑. next :=node; node ↑. p rev:=node;

   End   Els e    Begin     temp :=B Heap . firs t 〔pos 〕;

↑. prev ↑. nex t :=node ; temp

node ↑. p rev:=temp ↑. p rev; node ↑. next :=temp; temp ↑. prev:=node;

   End;

  node ↑. s tatus :=0;

If () 3. 2 桶空间截断算法

桶空间截断算法的基本思想是预先设置桶数组长度L. 在桶号为0~L -1所表示的距离范围内, 按照通常的办法来存储顶点. 而将当前最短路长超过0~L-1号桶所表示的距离范围的顶点存入L 号桶. 在算法中不断执行DeleteM in 运算, 一旦出现0~L-1号桶均为空桶时, 将L 号桶中顶点重新分布到0~L-1号桶中.

Procedure DeleteMin (var node :nodeP );  var bound, dis tn ew , posnew:longin t;    h ead, tail, nex tnode :nodeP;  Label rep;  Begin   rep :

   {找最小非空桶}

W hile ((BHeap. cur r

〔B Heap. cu rr 〕=Nil) ) Do

=1;

         1086

小 型 微 型 计 算 机 系 统

   BHeap . firs t 〔BHeap . curr 〕:=Nil

  Else    Begin

       2002年

   If (BHeap . cu rr =BHeap . s ize ) Then {0~L -1号桶均为空桶}    Begin

     If (BHeap . firs t 〔BHeap . size 〕Nil ) Th en {L 号桶非空}      Begin

       nod e :=B Heap . firs t 〔B Heap . size 〕;

↑. prev ↑. nex :nod e t =Nil ; {断开为非循环双链表}

:=BIG ; BHeap . bas e

w hile (node NIl ) do {计算新路长基数}

      Begin

       If node ↑. dis t

node ↑. dis t ; node :=node ↑. n ext ;

      End ;

     bound :=B Heap. base +BHeap. size; {顶点分布上界}

:=0; BHeap . cur r

tail :=Nil ; h ead :=Nil;

nod e :=B Heap. firs t 〔B Heap. size 〕;

~L -while (node NIl ) do {L 号桶中顶点重新分布到0

1号桶中}

      Begin

       nex tnode :=node ↑. next ;

distnew:=node ↑. dis t ;

If (distnew

        Begin

         BucketPos (distnew, pos new );

Ins ert(node, posnew );

        End

       Else{保留在L 号桶中}        Begin

         If (tail Nil) Then           Begin

           tail ↑. next :=node;

nod e ↑. prev:=tail;

          End

         Else h ead :=node;

tail :=node;

       End;

      nod e :=nextnode;      End;

    If (tail Nil) Then{置为循环链表}      Begin

       tail ↑. next :=head;

h ead ↑. prev:=tail ;

      End;

     BHeap. firs t 〔BHeap. size 〕:=h ead;

Goto rep;

    End

   Els e node :=Nil; {U= }  End

 Els e{cu rr 为最小非空桶号}  Begin

   node :=B Heap. firs t 〔BHeap. curr 〕;

node ↑. s tatus :=1;

  If . n     node ↑. prev ↑. n ext :=node ↑. nex t;

node ↑. nex t ↑. p rev :=node ↑. prev; BHeap. firs t 〔BHeap. curr 〕:=node ↑. nex t;

   End;   End; End;

由于数据结构的改变, 桶中顶点不需要循环存储, 根据当

前顶点的最短路长dista nce 计算出其应存入的桶号pos 的算法Bucket Po s (distance , pos ) 作相应调整如下.

:longint ; var pos :longint ); Procedure BucketPos (distance

 b egin

  pos :=distance-BHeap. bas e;

if pos >B Heap. size th en pos :=BHeap. size els e if pos

由此可设计出网络最短路的桶空间截断算法.

4 算法复杂性分析

4. 1 桶空间压缩算法的计算复杂性

桶空间压缩算法需要[C /L]个桶, 桶中每个顶点需要O (1) 存储空间. 除了紧凑邻接表所需要的O (m +n ) 空间外, 尚需O (n +C /L) 的存储空间. 因此桶空间压缩算法所需的存储空间为O (m +n +C /L ).

由于在桶空间压缩算法中, 每个桶中顶点是按照队列组织存放的, 所以一个顶点可能多次进出同一桶顶点队列. 而当同一顶点重复进入桶顶点队列时, 其当前最短距离至少减1. 因此同一顶点进入同一桶顶点队列的次数不超过L 次. 每个顶点进出队列一次所需的处理时间为O (1) , 每一条边所需的处理时间也是O (1) , 由此可见, 对桶中所有顶点进行处理所需的时间是O (L(m+n) ). 另一方面, 算法DeleteM in 的搜索非空桶的W hile 循环体需要O (C /L ) 计算时间, 而循环体最多被执行n 次, 因此算法中搜索非空桶所需的总时间为O (nC /L ).

综上可知, 桶空间压缩算法所需的计算时间为O (m L+n (L +C /L ) ). 4. 2 桶空间截断算法的计算复杂性

桶空间截断算法所需的空间显然为O (L +n ). 在桶空间截断算法中, 第0~L-1号桶中顶点的组织方式与桶算法完全一致. 桶中每个顶点恰被处理一次. 因此对桶中所有顶点进行处理所需的总时间为O (m +n). 桶空间截断算法与桶算法的主要区别在于截断的第L 号桶中顶点的重新分布. 在每一次作顶点重新分布时, 插入到0~L-1号桶中顶点所需的处理时间可用簿记的方法来计算. 每个顶点插入到每个桶中至多一次, 总共有L 个桶, 故所需的计算时间为O (nL). 另外, 在每一次重新分布后保留在第L 号桶中的顶点所需的处理时间也可用簿记的方法来计算. 每一次重新分布L 号L , L 号

9期       王晓东等:网络最短路问题的改进算法  

1087

多重新分布C /L 次. 每一次重新分布扫描一个顶点所需时间为O (1) , 因此保留在第L 号桶中顶点所需的处理时间为O (nC /L ).

综上可知, 桶空间截断算法所需的计算时间为O (m+n (L +C /L ) ).

在用桶空间压缩算法和桶空间截断算法且边权变化范围较大时取L =

U . 实际计算的结果如表2所示. 表2 大范围变边权实验结果

边权变化区间〔1. . 1〕〔0. . 10〕〔0. . 100〕〔0. . 10000〕〔0. . 1000000〕

桶算法1. 54. 129. 0323. 17内存溢出

桶空间压缩算法

2. 713. 884. 665. 806. 23

桶空间截断算法

1. 772. 072. 182. 233. 20

5 算法实验比较分析

对于网络最短路的桶算法和本文提出的桶空间压缩算法和桶空间截断算法从常规小边权和大范围变边权2个方面进行了实验比较, 所得的实验结果与理论分析完全一致. 5. 1 常规小边权实验结果对于边权在〔0…10〕范围内随机生成的非负网络用上述3个算法实际计算的结果如表1所示.

表1 常规小边权实验结果

结点数/边数桶算法桶空间压缩算法

512/655360. 090. 021024/262144

0. 46

0. 110. 481. 95

2048/10485761. 974096/41943048. 37

桶空间截断算法

0. 02

0. 120. 492. 02

表中所列计算时间为秒. 测试所用机型为P Ⅲ850, 128M 内存.

从上述实验结果可以看出, 当边权变化范围较大时, 桶空间压缩算法和桶空间截断算法均明显优于桶算法. 桶空间截断算法略优于桶空间压缩算法.

参 考 文 献

1Cormen T. H. , Leis ers on C. E. , R iv es t R. L. . Introduction to 〔M 〕. M IT Press , Camb ridg e , M A , 1990. 429~433algo rith ms

2Dial R . B. . Algo rith m 360:sho rtest path fores t w ith topological ordering 〔J 〕. Comm. ACM 12, 1969. 632~633

3Sahni S . . Data s tructures , algorithms , and applications in C ++〔M 〕. M cGraw Hill, New Yo rk , 1998. 569~570

4W ang Xiao -d ong . Th e d esing and analysis of comp uter algo rith ms 〔M 〕. Beijing :Publish ing House of Electronics Ind ustry. 2001(王晓东. 计算机算法设计与分析〔M 〕. 北京, 电子工业出版社. 2001. 94~96)

  表中所列计算时间为秒. 测试所用机型为P Ⅲ850, 128M

内存.

从上述实验结果可以看出, 对于常规小边权, 桶空间压缩算法和桶空间截断算法均优于桶算法. 桶空间压缩算法和桶空间截断算法之间的差别不大.

5. 2 大范围变边权实验结果

对于130000个结点和500000条且边权在〔L . . U 〕范围内随机变化的非负网络对上述3个算法进行实际计算比较.

Improved Algorithms for Network Shortest Paths Problem

W AN G Xia o-do ng , CHEN Guo-lo ng , L IN Bo-ga ng

(Computer Science Depar tment of F uzhou University , Fuz hou 350002, Ch ina )

Abstract  This paper discusses the desig n and im plementatio n strategies of the famo us Dijkstr a sho r test paths alg o rithm. The new techniques sugg ested improv e the time and space co mplexities o f the sho r test pa th s alg orithm sig nificantly . Key words  netw o rks; sho rtest paths; dijkstr a alg o rithm; algo rithm efficie ncy


相关内容

  • 城市道路最短路径的Dijkstra算法优化pdf
  • 第25卷 第6期2005年11月 长安大学学报(自然科学版) Journal of Chang πan University (Natural Science Edition ) Vol. 25 No. 6 Nov. 2005 文章编号:167128879(2005) 0620062204 城市道路 ...

  • 改进的配电网相间短路故障定位隔离算法
  • 第31卷第7期 ・48・ 2005年 7月 高电压技术 HighVoltageEngineering VbL31No.72005 July 改进的配电网相间短路故障定位隔离算法 刘春,刘云,魏天魁(华中科技大学,武汉430074) 摘要:分析了目前配电网相间短路故障定位和隔离算法中存在的一些问题(如 ...

  • 船舶电力系统短路电流计算方法研究
  • V01.29No.72009.7 船电技术2009年第7期 船舶电力系统短路电流计算方法研究 兰海赵岩 (哈尔滨工程大学自动化学院,哈尔滨150001) 摘 要:国家军用标准(GJB.173)计算法在计算船舶短路电流时,为求计算简便忽略较多,导致计算结果偏 大,这给配置船舶电力系统保护和设备选型带来 ...

  • 最短路问题的Floyd算法的若干讨论
  • 第22卷 第5期 Vol . 22 No . 5 重庆工学院学报(自然科学) Journal of Chongqing Institute of Technology (Natural Science ) 2008年5月Ma y 2008 最短路问题的Floyd 算法的若干讨论 郝自军1, 何尚录2 ...

  • 一种基于Dijkstra算法的启发式最优路径搜索算法
  • 第29卷第3期2007年3月 北J咖mal 京科技大学学报 VOI.29NO.3 ofUnive体ityofscienceand7Ikh∞Io留&ijiIIg Mar.2007 一种基于Dijkstra算法的启发式最优路径搜索算法 王景存1,2' 张晓彤1' 陈 彬2' 陈和平2' 1)北京 ...

  • 匈牙利算法
  • 求kM算法和匈牙利算法的程序代码 kM算法和匈牙利算法的程序代码,最好是用matlab给出的,用c语言亦可.不要用其他的编程语言. //二分图最佳匹配,kuhn munkras算法,邻接阵形式,复杂度O(m*m*n) //返回最佳匹配值,传入二分图大小m,n和邻接阵mat,表示权值 //match1 ...

  • 最短路径问题设计论文
  • 目 录 第1章 绪论 ........................................................................................................................................... ...

  • 公园道路最短路径问题
  • 公园道路最短路径问题 摘要 针对问题一:我们建立了基于floyd 算法的综合评价模型.我们根据题目所给的的信息,主要通过任意两点边线距离是否可用进行第一步筛选,选出个直连路径.根据题目所提供的原则,我们选取了路长和利用效率相结合的权值,并且构建了一种满足题目要求的路径,长度为472.5m 针对问题二 ...

  • USACO 4.2.1 Ditch 网络最大流问题算法小结
  • 通过 USACO 4.2.1 Ditch 学习一下最大流算法 .可惜它给的测试数据几乎没有任何杀伤力,后面测试时我们采用 DD_engi 写的程序生成的加强版数据. 总体上来说,最大流算法分为两大类:增广路 (Augmenting Path) 和预流推进重标号 (Push Relabel) .也有算 ...