主题:最短路径算法及应用
一、 队
1、队的定义:
队是特殊的线性表之一,它只允许在队的一端插入,在队的另一端删除。插入一端叫队尾(T),删除一端叫队首(H),没有任何元素的队叫做空队。队列遵循"先进先出"原则,排队购物、买票等,就是最常见的队。
[img]http://www.chinaschool.org/aosai/lwjl/images/02-0314-01.gif[/img]
2、队的基本操作:
(1)队的描述:
type queue=array[1..100] of integer;
var a:queue; {定义数组}
h,d:integer; {队首、队尾指针}
(2) 初始化(图1):
procedure start;
begin
h:=1; d:=1;
end;
(3) 入队操作(图2):
procedure enter;
begin
read(s); {读入数据}
inc(d); {队尾加一}
a[d]:=s;
end;
(4) 出队操作(图3):
procedure out;
begin
inc(h); {队首加一}
a[h]:=0;
end;
二、 广度优先搜索
广度优先搜索类似于树的按层次遍历的过程。它和队有很多相似之处,运用了队的许多思想,其实就是对队的深入一步研究,它的基本操作和队列几乎一样。
三、 队和广度优先搜索的运用
图4表示的是从城市A到城市H的交通图。从图中可以看出,从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。
[img]http://www.chinaschool.org/aosai/lwjl/images/02-0314-02.gif[/img]
图4
分析:看到这图很容易想到用邻接距阵来表示,0表示能走,1表示不能走。如图5。
[img]http://www.chinaschool.org/aosai/lwjl/images/02-0314-03.gif[/img]
图5
首先想到的是用队的思想。我们可以a记录搜索过程,a.city记录经过的城市,a.pre记录前趋元素,这样就可以倒推出最短线路。具体过程如下:
(1) 将城市A入队,队首、队尾都为1。
(2) 将队首所指的城市所有可直通的城市入队(如果这个城市在队中出现过就不入队,可用一个集合来判断),将入队城市的pre指向队首的位置。然后将队首加1,得到新的队首城市。重复以上步骤,直到城市H入队为止。当搜到城市H时,搜索结束。利用pre可倒推出最少城市线路。
以下为参考程序:
const ju:array[1..8,1..8] of 0..1=((1,0,0,0,1,0,1,1),
(0,1,1,1,1,0,1,1),
(0,1,1,0,0,1,1,1),
(0,1,0,1,1,1,0,1),
(1,1,0,1,1,1,0,0),
(0,0,1,1,1,1,1,0),
(1,1,1,0,0,1,1,0),
(1,1,1,1,0,0,0,1));
type r=record {记录定义}
city:array[1..100] of char;
pre:array[1..100] of integer;
end;
var h,d,i:integer;
a:r;
s:set of 'A'..'H';
procedure out; {输出过程}
begin
write(a.city[d]);
repeat
d:=a.pre[d];
write('--',a.city[d]);
until a.pre[d]=0;
writeln;
halt;
end;
procedure doit;
begin
h:=0; d:=1;
a.city[1]:='A';
a.pre[1]:=0;
s:=['A'];
repeat {步骤2}
inc(h); {队首加一,出队}
for i:=1 to 8 do {搜索可直通的城市}
if (ju[ord(a.city[h])-64,i]=0)and
(not(chr(i+64) in s))then {判断城市是否走过}
begin
inc(d); {队尾加一,入队}
a.city[d]:=chr(64+i);
a.pre[d]:=h;
s:=s+[a.city[d]];
if a.city[d]='H' then out;
end;
until h=d;
end;
begin {主程序}
doit;
end.
输出:
H-F--A
1、队的定义:
队是特殊的线性表之一,它只允许在队的一端插入,在队的另一端删除。插入一端叫队尾(T),删除一端叫队首(H),没有任何元素的队叫做空队。队列遵循"先进先出"原则,排队购物、买票等,就是最常见的队。
[img]http://www.chinaschool.org/aosai/lwjl/images/02-0314-01.gif[/img]
2、队的基本操作:
(1)队的描述:
type queue=array[1..100] of integer;
var a:queue; {定义数组}
h,d:integer; {队首、队尾指针}
(2) 初始化(图1):
procedure start;
begin
h:=1; d:=1;
end;
(3) 入队操作(图2):
procedure enter;
begin
read(s); {读入数据}
inc(d); {队尾加一}
a[d]:=s;
end;
(4) 出队操作(图3):
procedure out;
begin
inc(h); {队首加一}
a[h]:=0;
end;
二、 广度优先搜索
广度优先搜索类似于树的按层次遍历的过程。它和队有很多相似之处,运用了队的许多思想,其实就是对队的深入一步研究,它的基本操作和队列几乎一样。
三、 队和广度优先搜索的运用
图4表示的是从城市A到城市H的交通图。从图中可以看出,从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。
[img]http://www.chinaschool.org/aosai/lwjl/images/02-0314-02.gif[/img]
图4
分析:看到这图很容易想到用邻接距阵来表示,0表示能走,1表示不能走。如图5。
[img]http://www.chinaschool.org/aosai/lwjl/images/02-0314-03.gif[/img]
图5
首先想到的是用队的思想。我们可以a记录搜索过程,a.city记录经过的城市,a.pre记录前趋元素,这样就可以倒推出最短线路。具体过程如下:
(1) 将城市A入队,队首、队尾都为1。
(2) 将队首所指的城市所有可直通的城市入队(如果这个城市在队中出现过就不入队,可用一个集合来判断),将入队城市的pre指向队首的位置。然后将队首加1,得到新的队首城市。重复以上步骤,直到城市H入队为止。当搜到城市H时,搜索结束。利用pre可倒推出最少城市线路。
以下为参考程序:
const ju:array[1..8,1..8] of 0..1=((1,0,0,0,1,0,1,1),
(0,1,1,1,1,0,1,1),
(0,1,1,0,0,1,1,1),
(0,1,0,1,1,1,0,1),
(1,1,0,1,1,1,0,0),
(0,0,1,1,1,1,1,0),
(1,1,1,0,0,1,1,0),
(1,1,1,1,0,0,0,1));
type r=record {记录定义}
city:array[1..100] of char;
pre:array[1..100] of integer;
end;
var h,d,i:integer;
a:r;
s:set of 'A'..'H';
procedure out; {输出过程}
begin
write(a.city[d]);
repeat
d:=a.pre[d];
write('--',a.city[d]);
until a.pre[d]=0;
writeln;
halt;
end;
procedure doit;
begin
h:=0; d:=1;
a.city[1]:='A';
a.pre[1]:=0;
s:=['A'];
repeat {步骤2}
inc(h); {队首加一,出队}
for i:=1 to 8 do {搜索可直通的城市}
if (ju[ord(a.city[h])-64,i]=0)and
(not(chr(i+64) in s))then {判断城市是否走过}
begin
inc(d); {队尾加一,入队}
a.city[d]:=chr(64+i);
a.pre[d]:=h;
s:=s+[a.city[d]];
if a.city[d]='H' then out;
end;
until h=d;
end;
begin {主程序}
doit;
end.
输出:
H-F--A