图的广度优先搜索的应用
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图的广度优先搜索的应用
◆内容提要
广度优先搜索是分层次搜索,广泛应用于求解问题的最短路径、最少步骤、最优方法等方面。本讲座就最短路径问题、分酒问题、八数码问题三个典型的范例,从问题分析、算法、数据结构等多方面进行了讨论,从而形成图的广度优先搜索解决问题的模式,通过本讲座的学习,能明白什么样的问题可以采用或转化为图的广度优先搜索来解决。在讨论过程中,还同时对同一问题进行了深层次的探讨,进一步寻求解决问题的最优方案。
◆知识讲解和实例分析
和深度优先搜索一样,图的广度优先搜索也有广泛的用途。由于广度优先搜索是分层次搜索的,即先将所有与上一层顶点相邻接的顶点搜索完之后,再继续往下搜索与该层的所有邻接而又没有访问过的顶点。故此,当某一层的结点出现目标结点时,这时所进行的步骤是最少的。所以,图的广度优先搜索广泛应用于求解问题的最短路径、最少步骤、最优方法等方面。
本次讲座就几个典型的范例来说明图的广度优先搜索的应用。
先给出图的广度优先搜索法的算法描述:
F:=0;r:=1;L[r]:=初始值;
H:=1;w:=1;bb:=true;
While bb do
begin
H:=h+1;g[h]:=r+1;
For I:=1 to w do
Begin
F:=f+1;
For t:=1 to 操作数do
Begin
⑴m:=L[f]; {出队列};
⑵判断t操作对m结点的相邻结点进行操作;能则设标记bj:=0,并生成新结点;不能,则设标记bj:=1;
if bj:=0 then {表示有新结点生成}
begin
for k:=1 to g[h]-1 do
if L[k]=新结点then {判断新扩展的结点是否以前出现过}
begin
bj:=1;k:=g[h]-1
end;
if bj<>1 then {没有出现过} begin
r:=r+1;L[r]:=新结点;{新结点进队列}
b[r]:=f;c[r]:=t;{并链接指针,保存操作数} end; end; end; end;
w:=r+1-g[h];s:=0;{计算新生成的一层的结点数}
for k:=g[h] to r do {在新生成的一层结点中,判断是否有目标结点存在} if L[k]=目标结点 then begin
s:=s+1; {累计解的条数} 根据链接指针求出路径; end;
if s:<>0 then begin
输出s 条路径;
bb:=false; {设程序结束条件} end; end;
例1:最短路径问题
求从任意一个顶点V i 出发,对给出的图,求到达任意顶点V j (i<>j )的所有最短路径 [问题分析]
1、首先用邻接表表
示此图各端点的邻接关系。
2、数据结构
4 7
8
const
d:array[1..8,1..4] of byte=((2,3,4,0),(1,3,7,0),(1,2,4,5),(1,3,6,0),(3,6,7,8),(4,5,8,0),(2,5,8,0),(5,6,7,0))
{二维数组存放邻接表}
n:array[1..8] of byte=(3,3,4,3,4,3,3,3); {存放邻接顶点数}
var
L:array[1..64] of byte {队列}
F,r:byte {f队头指针,r队尾指针}
B:array[1..64] of byte {链接表,表示某一个结点的前趋结点}
G:array[1..10] of byte {表示层结点的首结点在队列开始的位置}
H:byte {搜索的层次}
由于搜索过的点不再进行搜索,故设置一个数组E[M]为标记,表示结点M是否访问过e:array[1..8] of 0..1;{用1表示已访问过,0表示还没有访问}
c:array[1..8,1..8]of byte; {C[s,j]存储到达目标结点后各最短路径的线路}
bb:Boolean {搜索结束标记}
3、算法描述
⑴设立初值,并令起始结点进队:
f:=0;r:=1;lL[r]:=st,E[st]:=1;w:=1;h:=1;
⑵将此时第h层(开始h=1,表示第一层)的w(开始时w=1,表示一个结点)顶点的顺序出队,并访问与该层各顶点相邻接但又没有访问过的顶点,同时将这些结点进队列,且设立前趋链接指针和访问过标记,若此时的结点为目标结点,则只设立前趋链接指针而不设立访问过标记
⑶计算此时第h+1层的顶点个数w:=r+1-g[h],然后看该层有多少个顶点为目标结点,凡是出现目标顶点的,就将其个数累计,也就是为最短路径的条数,同时从这个目标结点按前趋链接指针将到达该目标结点的路径的各个顶点编号存入c[s,j]中,然后转⑷,若目标顶点累计个数为0,表明该层没有出现目标结点,则转⑵。
⑷打印搜索到的各条最短路径的各结点编号,并结束程序。
程序如下:(见exp7_1.pas)
program exp7_1;
const
d:array[1..8,1..4] of byte=((2,3,4,0),(1,3,7,0),(1,2,4,5),(1,3,6,0),(3,6,7,8),(4,5,8,0),(2,5,8,0),(5,6,7,0));
n:array[1..8] of byte=(3,3,4,3,4,3,3,3);
var
L,b:array[1..64] of byte;
F,r,h,m,st,ed,I,j,t,k,s,p,w:byte;
G:array[1..10] of byte;
e:array[1..8] of 0..1;
c:array[1..8,1..8]of byte;
bb:Boolean;
begin
write('start:');readln(st);
write('end:');readln(ed);
fillchar(e,sizeof(e),0); {标记数组清零}
fillchar(c,sizeof(c),0); {路径数组清零}