第一讲 图的搜索算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构设计:
用数组做队的存储空间,队中结点有三个 成员:行号、列号、前一个方格在队列中的 下标。搜索过的方格不另外开辟空间记录其 访问的情况,而是用迷宫原有的存储空间置 元素值为“-1”时,标识已经访问过该方格。 为了构造循环体,用数组fx={1,-1,0,0}、 fy={ 0,0,-1,1 }模拟上下左右搜索时的下标 的变化过程。
• 4、算法说明: • 1)和广度优先算法一样每个方格有四个方 向可以进行搜索,这样一点结点(方格) 就可多次成为“活结点”,而在广度优先 算法一点结点(方格)就可一次成为“活 结点”,一出队就成了死结点。 • 2)用广度优先算法,搜索出的是一条最短 的路径,而用深度优先搜索则只能找出一 条可行的路径,而不能保证是最短的路径。 • 3)在空间效率上二者相近。都需要辅助空 间。
• 需要说明的是,深度优先搜索的访问顺序与图的邻接表存储状态有关,由于图的邻接 表的存储不是惟一,因此同一个图,其深度优先遍历的结果也可能不同,但采用邻接 矩阵或邻接表存储结构内容已确定的图的DFS序列将是确定的。
1.算法的基本思路
算法设计的基本步骤为: 1)确定图的存储方式; 2)遍历过程中的操作,其中包括为输出 问题解而进行的存储操作; 3)输出问题的结论。 4)一般在回溯前的应该将结点状态恢复 为原始状态,特别是在有多解需求的问题中。
下面给出深度优先搜索的一个实例
v1
v2
起点
DFS 结果
v3 v5 v6 v7
•
v4
v1→ v2 v4→v8 → → → v5→v3 →v6 v7
v8 • 深度优先搜索的步骤
详细归纳: E 在访问图中某一起始顶点 v 后,由 v 出发,访问它的任一邻接顶点 w1; E 再从 w1 出发,访问与 w1邻接但还未被访问过的顶点 w2; 然后再从 w2 出发,进行类似的访问,… 如此进行下去,直至到达所有的邻接顶点都被访问过的顶点 u 为止。
或改造,加入了一定的“智能因素”,使搜索能尽快接近目标结点,减少了在空间和 时间上的复杂度。 )
二、分支定界 三、A*算法 第三部分 搜索与动态规划的结合 (包括与其他算法的联系和对比)
初级的图搜索算法
• 包括 深度优先遍历,广度优先遍历和双向广度优先遍历 • 图的两种遍历算法:深度优先搜索和广度优先搜索算法 • BFS是一种盲目搜寻法,目的是系统地展开并检查图中 的所有节点,以找寻结果。换句话说,它并不考虑结果 的可能位址,彻底地搜索整张图,直到找到结果为止。 BFS并不使用经验法则算法。
深度优先搜索
用深度优先搜索策略遍历一个图类似于树的前序遍历,它是树 的前序遍历方法的推广.这种搜索方法称为深度优先搜索(DepthFirst Search)。 深度优先搜索(DFS)的基本思想是:对于给定的图G=(V,E) 首先将V中每一个顶点都标记为未被访问,然后,选取一个源点v 属于V,将v标记为已被访问,再递归地用深度优先搜索方法,依 次搜索v的所有领接点w。若w未被访问,则以w为新的出发点继 续深度优先遍历,如果从v出发的路的顶点都已被访问过,则从v的 搜索过程结束。若还有未被访问过的顶点,则再任选个顶点开始 新的搜索,直至所有顶点被访问过为止。 用深度优先搜索方法遍历图称为图的深度优先遍历。
如图5-6表示的是从城市A到城市H的交通图。从图中可 以看出,从城市A到城市H要经过若干个城市。现要找出一条 经过城市最少一条路线。 (提示:看到这图很容易想到用邻接距阵来表示,0
表示能走,1表示不能走。如图5--6。)
图5-6
表5-1
图5-6的邻接距阵
具体过程如下:
1)将城市A(编号1)入队,队首qh置 为0、队尾qe置为1。 2)将队首所指的城市所有可直通的城 市入队(如果这个城市在队中出现过就不 入队),然后将队首加1,得到新的队首城 市。重复以上步骤,直到城市H入队为止。 当搜到城市H时,搜索结束。 3)输出最少城市线路。
广度优先搜索
与深度优先搜索方法不一样,广度优先搜索方法没有探查和回溯 的过程,而是一个逐层遍历的过程.类似于树的层次遍历,采用的搜 索方法的特点是尽可能先对横向结点进行搜索,故称为广度优先 搜索(BFS) 其基本思想:从图G=(V,E)的某个源点v出发,在 访问了顶点v之后,接着尽可能先在横向搜索v的所有邻接点。在 依次访问v的各个未被访问过的邻接点w1,w2…之后,分别从这 些邻接点出发依次访问与w1,w2….邻接的所有未曾访问过的顶 点,依次直至图中所有和源点v有路径想通的顶点都已被访问过为 止,此时从v开始的搜索过程结束。若G是连通图,则遍历完成; 否则在图中另选一个尚未被访问过的点作为源点继续上述搜索过 程。
print(“Total is”,total); }
•search(int i, int j) {int k,newi,newj; for(k=1;k<=4;k++) //搜索可达的方格 if(check(i,j,k)=1) {newi=i+fx[k]; newj=j+fy[k]; maze[newi][newj]=3; //来到新位置后,设置已走过标志/ if (newi=8 and newj=8) //到出口则输出,否则下一步递归 else } maze[i][j]=2; } /某一方格只能走入死胡同/
算法设计:
从入口开始广度优先搜索可到达的方格入队,再扩展 队首的方格,直到搜索到出口时算法结束。 对于迷宫中任意一点A(Y,X),有四个搜索方向: 向上A(Y-1,X) //Y为纵,X为横 向下A(Y+1,X) 向左A(Y,X-1) 向右A(Y,X+1) 当对应方格可行(值为0),就扩展为活结点。
广度优先搜索的应用
【例1】已知若干个城市的地图,求从一个 城市到另一个城市的路径,要求路径中经过的 城市最少 【例2】走迷宫问题
·
【例1】已知若干个城市的地图,求从一个城市到 另一个城市的路径,要求路径中经过的城市最少。
算法设计:
图的广度优先搜索类似与树的层次遍 历,逐层搜索正好可以尽快找到一个结点 与另一个结点相对而言最直接的路径。
采用广度优先搜索法遍历图的方法称为图的广度优先遍历。
广度优先搜索(BFS)
• 基本思想:——仿树的层次遍历过程 • v • • v2 v4 v5 v6 v3 v7
BFS 结果
v1→v2→v3→v4→v5 →v6 → v7 →v8
v8
分层的搜索过程,每向前走一步可能访问一批顶点,不像深度优 先搜索那样有回退的情况。 因此,广度优先搜索不是一个递归的过程,其算法也不是递归的。
算法框架
1.算法的基本思路 算法设计的基本步骤为:
1)确定图的存储方式; 2)图的遍历过程中的操作,其中包括为输 出问题解而进行的存储操作;
3)输出问题的结论。
dfs与bfs 深度搜索与广度搜索的相近,最终都要扩展 一个结点的所有子结点. 区别在于对扩展结点过程,深度搜索扩 展的是E-结点的邻接结点中的一个,并将其 作为新的E-结点继续扩展,当前E-结点仍为 活结点,待搜索完其子结点后,回溯到该结 点扩展它的其它未搜索的邻接结点。而广度 搜索,则是扩展E-结点的所有邻接结点,E结点就成为一个死结点。
check(int i,int j,int k) {int flag=1; i= i+fx[k]; j= j +fy[k]; if(i<1 or i>8 or j<1 or j>8) /是否在迷宫内/ flag=0; else if(maze[i][j]<>0) /是否可行/ flag=0; return(flag); }
回溯法
回溯算法实际是一个类似枚举的搜索尝试方法,它的主题思想是在搜索尝试 中找问题的解,当不满足求解条件就”回溯”返回,尝试别的路径。回溯算法是 尝试搜索算法中最为基本的一种算法,其采用了一种“走不通就掉头”的思想, 作为其控制结构。回溯法中,首先需要明确下面三个概念: (一)约束函数:约束函数是根据题意定出的。通过描述合法解的一般特征用于 去除不合法的解,从而避免继续搜索出这个不合法解的剩余部分。因此,约束函 数 是 对 于 任 何 状 态 空 间 树 上 的 节 点 都 有 效 、 等 价 的 。 (二)状态空间树:刚刚已经提到,状态空间树是一个对所有解的图形描述。树 上 的 每 个 子 节 点 的 解 都 只 有 一 个 部 分 与 父 节 点 不 同 。 (三)扩展节点、活结点、死结点:所谓扩展节点,就是当前正在求出它的子节 点的节点,在DFS中,只允许有一个扩展节点。活结点就是通过与约束函数的对 照,节点本身和其父节点均满足约束函数要求的节点;死结点反之。由此很容易 知 道 死 结 点 是 不 必 求 出 其 子 节 点 的 ( 没 有 意 义 ) 。
Out( ); search(newi,newj);
• Out( ) • { int i,j; for( i=1;i<=8;i++) • { print(“换行符”); • for(j=1;j<=8;j++) • if(maze[i][j]=3) • {print(“V”); • total++;} /统计总步数/ • else • print(“*”); • } • }
深度优先搜索的应用
•【例1】走迷宫问题:问题同【例2】 •1、算法设计:深度优先搜索,就是一直向 着可通行的下一个方格行进,直到搜索到出 口就找到一个解。若行不通时,则返回上一 个方格,继续搜索其它方向。
•3、算法(给出的不是真正的程序代码,只是伪代码.所以它 的程序里面数组下标是从1开始,而实际上C语言里面数组下 标是从0开始,你要把程序中相应的地方改掉. ) int maze[8][8]={{0,0,0,0,0,0,0,0}, {0,1,1,1,1,0,1,0},{0,0,0,0,1,0,1,0},
{0,1,0,0,0,0,1,0},{0,1,0,1,1,0,1,0}, {0,1,0,0,0,0源自文库1,1},{0,1,0,0,1,0,0,0}, {0,1,1,1,1,1,1,0}};fx[4]={1,-1,0,0}, fy[4]={0,0,-1,1}; main( ) { int total=0; maze[1][1]=3; search(1,1); /入口坐标设置已走标志/ /统计总步数/ int i,j,k,total;
图的搜索算法
10.R4.李洪杰
问题引入 • 如图表示的是从城市A到城市H的交通图。从图中可以 看出,从城市A到城市H要经过若干个城市。现要找出 一条经过城市最少一条路线。
走迷宫问题
图的搜索算法了解
第一部分 基本搜索算法 一、回溯算法 二、深度搜索与广度搜索 第二部分 搜索算法的优化 一、双向广度搜索(双向搜索和A算法对广度优先的搜索方式进行了改良
·
数据结构设计:
1)线性数组a作为活结点队的存储空间。 2)队列的每个结点有两个成员:a[i].city记 录入队的城市,a[i].pre记录该城市的前趋城 市在队列中的下标,这样通过a[i].pre就可以 倒推出最短线路。 3)设置数组visited[]记录已搜索过的城市。
【例2】走迷宫问题
迷宫是许多小方格构成的矩形,在每个小方格中有的是墙(图中的 “1”)有的是路(图中的“0”)。走迷宫就是从一个小方格沿上、下、左、 右四个方向到邻近的方格,当然不能穿墙。设迷宫的入口是在左上角(1,1), 出口是右下角(8,8)。根据给定的迷宫,找出一条从入口到出口的路径。
认识回溯法
【例1】八皇后问题模型建立 要在8*8的国际象棋棋盘中放八个皇后, 使任意两个皇后都不能互相吃掉。规则:皇 后能吃掉同一行、同一列、同一对角线的任 意棋子。如图5-12为一种方案,求所有的解。
• 模型建立
不妨设八个皇后为xi,她们分别在第i行 (i=1,2,3,4……,8),这样问题的解空 间,就是一个八个皇后所在列的序号,为n元 一维向量(x1,x2,x3,x4,x5,x6,x7,x8),搜 索空间是1≤xi≤8(i=1,2,3,4……,8), 共88个状态。约束条件是八个(1,x1),(2,x 2) ,(3,x3),(4,x4) ,(5,x5), (6,x6) , (7, x7), (8,x8)不在同一行、同一列和同一对角 线上。