广度搜索文档格式.docx

上传人:b****5 文档编号:18198148 上传时间:2022-12-14 格式:DOCX 页数:18 大小:55.13KB
下载 相关 举报
广度搜索文档格式.docx_第1页
第1页 / 共18页
广度搜索文档格式.docx_第2页
第2页 / 共18页
广度搜索文档格式.docx_第3页
第3页 / 共18页
广度搜索文档格式.docx_第4页
第4页 / 共18页
广度搜索文档格式.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

广度搜索文档格式.docx

《广度搜索文档格式.docx》由会员分享,可在线阅读,更多相关《广度搜索文档格式.docx(18页珍藏版)》请在冰豆网上搜索。

广度搜索文档格式.docx

=i;

=pnt[i];

end;

write('

Dep='

n-1,'

:

1'

);

forj:

=n-1downto1dobegin

->

'

qm[s[j]]);

readln;

end;

f[1]:

=[1]{城市1已到};

qm[1]:

=1{队列的第一个节点是1};

pnt[1]:

{没有父辈节点}

closed:

open:

=1;

repeat

inc(closed);

k:

=qm[closed];

ifk<

>

6thenbegin

=f[closed];

fori:

=2to6do

if(not(iinfs))and(link[k,i]>

0)thenbegin

inc(open);

qm[open]:

f[open]:

=fs+[i];

pnt[open]:

=closed;

ifi=6thenprint;

untilclosed>

end.

在广度优先搜索中,我们将扩展出来的结点存贮在一个称作qm的数组里,qm数组采用“先进先出”的队列结构,设两个指针closed和open,分别是队首指针和队尾指针。

其中qm[1..closed-1]存贮已扩展的结点(即这些结点的子结点已扩展出);

qm[closed..open]存贮待扩展结点(即这些结点的子结点尚待扩展)。

当closed>

=open则表示队列空,结束。

pnt为父辈结点数组,它记录了每个结点的父辈结点,当找到目标后,可沿着父辈结点倒串上去,输出路径方案。

在广度优先搜索中,第一个达到目标结点的,即是最短路径。

例1-2-2有一个由四个1和四个0,中间有一个空格组成的字符串‘11110000’,现规定:

①1只能向右运动,0只能向左运动。

②空格左右的1或0可以移动,进入空格。

③1可以跳过一个0,进入空格;

0也可以跳过一个1,进入空格。

要求在符合上述规定的方式下,以最少的步骤,将其变为字符串‘00001111’,编程打印输出运动的每一步。

a9=string[9];

qt=record

a:

a9;

x,pnt:

qm:

array[byte]ofqt;

temp:

qt;

closed,open:

Procedureprint;

Var

buf:

array[1..30]ofbyte;

i,j:

begin

j:

=0

inc(j);

buf[j]:

=qm[i].pnt;

=jdownto1dobegin

No.'

i-j:

2,'

qm[buf[i]].a);

halt;

procedurecomp;

vari:

=1toopendo

ifqm[i].a=temp.athenexit;

=open+1;

qm[open].a:

=temp.a;

qm[open].x:

=temp.x;

qm[open].pnt:

iftemp.a='

00001111'

thenprint;

procedureopa;

withtempdo

if(x>

1)and(a[x-1]='

1'

)thenbegin

a[x-1]:

='

;

a[x]:

x:

=x-1;

comp;

procedureopb;

if(x<

9)and(a[x+1]='

0'

a[x+1]:

=x+1;

procedureopc;

2)and(a[x-1]='

)and(a[x-2]='

a[x-2]:

=x-2;

procedureopd;

8)and(a[x+1]='

)and(a[x+2]='

a[x+2]:

=x+2;

withqm[1]dobegin

11110000'

=5;

pnt:

whileclosed<

opendobegin

=closed+1;

opa;

opb;

opc;

opd;

例1-2-3在魔方风靡全球后,Rubik先生发明了它的简化版——魔板,如下图:

魔板由6个同样大小的方块组成,每个方块的颜色均不相同,本题中用数字1–6分别表示,可能出现在魔板的任一位置。

对魔板可施加三种不同的操作,分别以a、b、c标识,具体操作方法如下:

应用三种基本操作,可由任一状态到达任意另一状态。

编一程序,对于输入的一个初始状态和一个目标状态,寻找一种最少的操作步骤,打印输出从初始状态到目标状态的每一步操作和状态值。

x,y:

integer;

op:

char;

array[1..720]ofqt;

closed,open,k,l,m,n:

array[1..30]ofinteger;

=j+1;

s[j]:

writeln(qm[1].x);

writeln(qm[1].y);

writeln;

=j-1downto1dobegin

writeln('

Oprate:

qm[s[i]].op);

writeln(qm[s[i]].x);

writeln(qm[s[i]].y);

procedurecomp(opx:

char);

if(m=qm[i].x)and(n=qm[i].y)thenexit;

=m;

qm[open].y:

=n;

qm[open].op:

=opx;

if(m=k)and(n=l)thenprint;

m:

=qm[closed].y;

=qm[closed].x;

comp('

a'

=(qm[closed].xmod10)*100+(qm[closed].xdiv10);

=(qm[closed].ymod10)*100+(qm[closed].ydiv10);

b'

a,b,c,d:

=qm[closed].xdiv100;

b:

=qm[closed].xmod100div10;

c:

=qm[closed].ydiv100;

d:

=qm[closed].ymod100div10;

=c*100+a*10+(qm[closed].xmod10);

=d*100+b*10+(qm[closed].ymod10);

c'

InputSourceM(1,2,3):

readln(qm[1].x);

InputSourceN(6,5,4):

readln(qm[1].y);

InputObjectK(1,2,3):

readln(k);

InputObjectL(6,5,4):

readln(l);

qm[1].pnt:

例1-2-4八数码问题:

在3*3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一个数字,棋盘上留有一个空格,空格周围的棋子可以移到空格中。

要求给出一种初始状态和一种目标状态,找出一种最少步骤的移动方法,实现从初始状态到目标状态的转变。

例如:

初始状态目标状态

283123

16484

75765

Type

a33=array[1..3,1..3]ofbyte;

a4=array[1..4]of-1..1;

node=record

ch:

a33;

y,x:

word;

Const

start:

a33=((2,8,3),(1,6,4),(7,0,5));

goal:

a33=((1,2,3),(8,0,4),(7,6,5));

x1=2;

y1=3;

max=4800;

dx:

a4=(0,-1,0,1);

dy:

a4=(-1,0,1,0);

Var

data:

array[1..max]ofnode;

node;

r,tx,ty:

Functioncheck(k:

byte):

boolean;

ty:

=temp.y+dy[k];

tx:

=temp.x+dx[k];

if(tyin[1..3])and(txin[1..3])

thencheck:

=true

elsecheck:

=false;

Functiondupe:

j,k:

inc(i);

=true;

=1to3do

fork:

ifdata[i].ch[j,k]<

data[open].ch[j,k]thenb:

untilbor(i>

=open-1);

dupe:

=b;

Functiongoals:

Vari,j:

goals:

ifdata[open].ch[i,j]<

goal[i,j]thenexit;

Proceduretrace;

closed='

closed,'

open='

open,'

oprater='

r);

=1to3dobegin

ifdata[open].ch[i,j]=0thenwrite('

elsewrite(data[open].ch[i,j]);

writeln

array[1..20]ofword;

k,n:

inc(n);

b[n]:

=data[i].pnt;

Staps:

n-1:

5);

=ndownto1dobegin

ifdata[b[k]].ch[i,j]=0

thenwrite('

elsewrite(data[b[k]].ch[i,j]);

withdata[1]dobegin

=start;

y:

=y1;

=x1;

=data[closed];

forr:

=1to4do

ifcheck(r)thenbegin

data[open]:

=temp;

withdata[open]dobegin

ch[y,x]:

=ch[ty,tx];

ch[ty,tx]:

=ty;

=tx;

{trace;

}

ifdupethendec(open)

elseifgoalsthenprint;

until(closed>

=open)or(open>

max-3);

Nosolution!

'

 

二、队列与广度优先搜索

队列是不同于栈的另一种线性表。

在日常生活中,无论是购物、订票或候车都有可能要排队。

排队所遵循的原则是“先来先服务”,后来者总是加到队尾,排头者总是先离开队伍。

队列就是从日常生活中的排队现象抽象出来的。

所谓队列,就是允许在一端进行插入,在另一端进行删除的线性表。

允许插入的一端称为队尾,通常用一个队尾指针open指向队尾元素,即open总是指向最后被插入的元素;

允许删除的一端称为队首,通常也用一个队首指针closed指向排头元素的前面。

初始时closed=open=0(如图)。

显然,在队列这种数据结构中,最先插入在元素将是最先被删除;

反之最后插入的元素将最后被删除,因此队列又称为“先进先出”(FIFO—firstinfirstout)的线性表。

与栈相似,队列的顺序存储空间可以用一维数组q[1‥m]模拟:

Q:

1m

我们按照如下方式定义队列:

M=队列元素的上限;

Equeue=array[1..m]ofqtype;

{队列的类型定义}

Var

equeue;

{队列}

open,closed:

integer;

{队尾指针和队首指针}

队列的运算主要有两种

1.过程ADD(qm,x,open)—在队列qm的尾端插入元素x

procedureADD(varqm:

equeue;

qtype;

varopen:

integer);

ifopen=m

thenwriteln(‘Overflow’){上溢}

elsebegin{后移队尾指针并插入元素x}

=x;

end;

2.过程DEL(qm,y,closed,open)—取出qm队列的队首元素y

procedureDEL(varqm:

vary:

varclosed,open:

ifclosed=open

thenwriteln(‘underflow’){下溢}

elsebegin{后移队首指针并取出队首元素}

=closed+1;

y:

=qm[closed];

由于队列只能在一端插入,在另一端删除,因此随着入队及出队运算的不断进行,就会出现一种有别于栈的情形:

队列在数组中不断地向队尾方向移动,而在队首的前面产生一片不能利用的空闲存储区,最后会导致当尾指针指向数组最后一个位置(即open=m)而不能再加入元素时,存储空间的前部却有一片存储区无端浪费,这种现象称为“假溢出”。

下图给出了一个“假溢出”的示例:

m

Open→m

Am

“假溢出”

A4

open→3

A3

closed→3

Closed→3

2

A2

2

1

1

A1

Closed,open→Closed→

初始时队列空加入三个元素删除三个元素队列空加入m-3个元素队列满

closed=open=0closed=0open=3closed=open=3closed=3open=m

为了解决“假溢出”的问题,我们不妨作这样的设想:

在队列中,当存储空间的最后一个位置已被使用而要进行入队运算时,只要存储空间第一个位置空闲,便可将元素加入到第一个位置,即将存储空间的第一个位置作为队尾。

采用首尾相接的队列结构后,可以有效地解决假溢出的问题,避免数据元素的移动,这就是所谓的循环队列。

下图给出了循环队列的结构。

循环队列将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用,循环队列的存取方法亦为“先进先出”。

对循环队列操作有以下几种状态:

初始时队列空,队首指针和队尾指针均指向存储空间的最后一个位置,

即closed=open=m。

●入队运算时,尾指针进一,即

open:

=open+1;

ifopen=m+1thenopen:

=1;

这两条语句可用一条语句替代:

=openmodm+1;

●出队运算时,首指针进一,即

ifclosed=m+1thenclosed:

=closedmodm+1;

●队列空时有closed=open。

●队列满时有closed=openmodm+1。

(为了区分队列空和队列满,改用“队尾指针追上队首指针”这一特征作为队列满标志。

这种处理方法的缺点是浪费队列空间的一个存储单元)

循环队列的运算有两种:

1.过程ADD2(qm,x,open)—在循环队列qm中插入一个新元素x

procedureADD2(varqm:

e

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1