迷宫求解问题资料
数据结构课程设计迷宫问题求解

数据结构课程设计迷宫问题求解正文:一、引言在数据结构课程设计中,迷宫问题求解是一个经典且常见的问题。
迷宫问题求解是指通过编程实现在迷宫中找到一条从起点到终点的路径。
本文将详细介绍如何用数据结构来解决迷宫问题。
二、问题分析1.迷宫定义:迷宫是由多个格子组成的矩形区域,其中包括起点和终点。
迷宫中的格子可以是墙壁(无法通过)或者通道(可以通过)。
2.求解目标:在给定的迷宫中,找到从起点到终点的一条路径。
3.输入:迷宫的大小、起点坐标、终点坐标以及墙壁的位置。
4.输出:从起点到终点的路径,或者提示无解。
三、算法设计1.基础概念a) 迷宫的表示:可以使用二维数组来表示迷宫,数组的元素可以是墙壁、通道或者路径上的点。
b) 坐标系统:可以使用(x, y)来表示迷宫中各个点的坐标。
c) 方向定义:可以用上、下、左、右等四个方向来表示移动的方向。
2.深度优先搜索算法(DFS)a) 算法思想:从起点开始,沿着一个方向一直走到无法继续为止,然后回退到上一个点,再选择其他方向继续探索。
b) 算法步骤:i) 标记当前点为已访问。
ii) 判断当前点是否为终点,如果是则返回路径;否则继续。
iii) 遍历四个方向:1.如果该方向的下一个点是通道且未访问,则继续向该方向前进。
2.如果该方向的下一个点是墙壁或已访问,则尝试下一个方向。
iv) 如果四个方向都无法前进,则回退到上一个点,继续向其他方向探索。
3.广度优先搜索算法(BFS)a) 算法思想:从起点开始,逐层向外探索,直到找到终点或者所有点都被访问。
b) 算法步骤:i) 标记起点为已访问,加入队列。
ii) 循环以下步骤直到队列为空:1.取出队首元素。
2.判断当前点是否为终点,如果是则返回路径;否则继续。
3.遍历四个方向:a.如果该方向的下一个点是通道且未访问,则标记为已访问,加入队列。
iii) 如果队列为空仍未找到终点,则提示无解。
四、算法实现1.选择合适的编程语言和开发环境。
迷宫问题算法

迷宫问题算法一、引言迷宫问题是一个经典的算法问题,对于寻找路径的算法有着广泛的应用。
迷宫是一个由通路和墙壁组成的结构,从起点出发,要找到通往终点的路径。
迷宫问题算法主要解决的是如何找到一条从起点到终点的最短路径。
二、DFS(深度优先搜索)算法深度优先搜索算法是迷宫问题求解中最常用的算法之一。
其基本思想是从起点开始,沿着一个方向不断向前走,当走到无法继续前进的位置时,回退到上一个位置,选择另一个方向继续前进,直到找到终点或者无路可走为止。
1. 算法步骤1.初始化一个空栈,并将起点入栈。
2.当栈不为空时,取出栈顶元素作为当前位置。
3.如果当前位置是终点,则返回找到的路径。
4.如果当前位置是墙壁或者已经访问过的位置,则回退到上一个位置。
5.如果当前位置是通路且未访问过,则将其加入路径中,并将其邻居位置入栈。
6.重复步骤2-5,直到找到终点或者栈为空。
2. 算法实现伪代码以下为DFS算法的实现伪代码:procedure DFS(maze, start, end):stack := empty stackpath := empty listvisited := empty setstack.push(start)while stack is not empty docurrent := stack.pop()if current == end thenreturn pathif current is wall or visited.contains(current) thencontinuepath.append(current)visited.add(current)for each neighbor in getNeighbors(current) dostack.push(neighbor)return "No path found"三、BFS(广度优先搜索)算法广度优先搜索算法也是解决迷宫问题的常用算法之一。
数据结构迷宫求解

数据结构迷宫求解迷宫问题是一种常见的求解问题,通过在迷宫中找到从起点到终点的路径。
在计算机科学中,使用数据结构来解决迷宫问题非常方便。
本文将介绍迷宫问题的基本原理、常见的求解方法以及使用不同数据结构的优缺点。
首先,我们需要明确迷宫的基本定义。
迷宫可以看作是一个二维的网格,其中包含一些墙壁和通路。
起点是迷宫的入口,终点则是迷宫的出口。
我们的目标是找到从起点到终点的一条路径。
迷宫问题可以使用多种算法求解,包括深度优先(DFS)、广度优先(BFS)、最短路径算法等。
以下将详细介绍这些算法以及它们在迷宫问题中的应用。
同时,我们还会讨论不同数据结构在求解迷宫问题中的优缺点。
首先,深度优先(DFS)是一种常用的求解迷宫问题的算法。
该算法从起点开始,一直到终点,期间遇到墙壁或已经访问过的点则回溯到上一个节点。
DFS可以使用递归实现,也可以使用栈来保存需要回溯的节点。
DFS的优点是简单易懂,易于实现。
然而,它可能会陷入死循环或者找到一条较长的路径而不是最短路径。
另一种常见的算法是广度优先(BFS),它从起点开始,逐层扩展,直到找到终点为止。
BFS可以使用队列来保存每一层的节点。
与DFS相比,BFS能够找到最短路径,但它需要维护一个较大的队列,从而增加了空间复杂度。
除了DFS和BFS,还有一些其他算法可以应用于迷宫问题。
例如,迪杰斯特拉算法和A*算法可以找到最短路径。
这些算法使用了图的概念,将迷宫中的通道表示为图的边,将各个节点之间的距离表示为图的权重。
然后,通过计算最短路径的权重,找到从起点到终点的最短路径。
迪杰斯特拉算法和A*算法的优点是能够找到最短路径,但它们的实现较为复杂。
在使用这些算法求解迷宫问题时,我们需要选择适合的数据结构来存储迷宫和过程中的状态。
以下是几种常见的数据结构以及它们的优缺点:1.数组:数组是一种常见的数据结构,它可以用来表示迷宫。
可以使用二维数组来表示迷宫的网格,并使用特定的值表示墙壁和通路。
迷宫求解

}PosType; //位置的元素类型
这样判断其可通与否的语句为
if (maze[CurPos.row][CurPos.line]==0)
1.迷宫的初始化
void Initmaze(int maze[12][12],int size); //初始化迷宫
迷宫的初始化有两种方法,一是随即生成,一是手动设置,由用户选择。随即生成的方法是程序生成随机数,除以2取余
maze[i][j]=rand()%2;
手动设置是用户输入0,1由程序读取
尺寸大小size可以设置,但是不能超过10,因为二维数组第一行,最后一行,第一列,最后一列一定要是不可通的,这是算法中用到的一个技巧。
迷宫内通道块位置变量类型定义为PosType
typedef struct
{
int row; //row表示“行”号
{
Markfoot(maze,curpos); // 留下足迹
e.di =1;
e.ord = curstep;
e.seat= curpos;
Push(S,e); // 加入路径
一、上机实验的问题和要求:迷宫问题(书P50 3.2.4和《数据结构题集》P105 2.9):以一个m×n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。
利用链栈结构,然后编写一个求解迷宫的非递归程序。求得的通路以三元组(i,j,d)的形式输出,其中:(i,j)指示迷宫中的一个坐标,d表示走到下一坐标的方向。如:对于下列数据的迷宫,输出的一条通路为:(1,1,1),(1,2,2),(2,2,2),(3,2,3),….。
实验3 迷宫求解

实验3 迷宫求解一、实验目的学会建立迷宫,在迷宫中寻找任意两坐标间是否存在路径,显示出该路径。
并熟练应用“栈”。
二、实验内容1、在计算机中用0、1图表示迷宫,0和1分别表示迷宫中的通路和障碍。
所求路径必须是简单路径,即在求得的路径上不能重复出现同一通道。
假设“当前位置”指的是“在搜索过程中的某一时刻所在图中某个位置”,则求迷宫中一条路径的算法的基本思想是:若当前位置“可通”,则纳入“当前路径”,并继续朝“下一位置”探索,即切换“下一位置”为“当前位置”,如此重复直至到达出口;若当前位置“不可通”,则应顺着“来向”退回到“前一通道”,然后朝着除“来向”之外的其他方向继续探索;若该通道块的四周4个方向均“不可通”,则应从“当前路径”上删除该通道。
所谓“下一位置”指的是当前位置四周4个方向(东、南、西、北)“1”。
假设以栈S记录“当前路径”,则栈顶中存放的是“当前路径上最后一个通道”。
由此,“纳入路径”的操作即为“当前位置入栈”;“从当前路径上删除前一通道”的操作即为“出栈”。
若当前位置可通,则纳入当前路径,并继续朝下一个位置探索,即切换下一位置为当前位置,如此重复直至到达出口;若当前位置不可通,则应顺着来向退回到前一通道块,然后朝着除来向之外的其他方向继续探索;若该通道块的四周4个方块均不可通,则应从当前路径上删除该通道块.设以栈记录当前路径,则栈顶中存放的是当前路径上最后一个通道块.由此,纳入路径的操作即为当前位置入栈;从当前路径上删除前一通道块的才操作即为出栈.2、求迷宫中一条从入口到出口的路径的算法可简单描述如下:设顶当前位置的初值为入口位置;Do{若当前位置可通,则{ 将当前位置插入栈顶; //纳入通路若该位置是出口位置,则结束; //求得路径存放在栈中否则切换当前位置的东邻方块为新的当前位置;}否则,若栈不空切栈顶位置尚有其他方向未经探索,则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;若栈不空但栈顶位置的四周均不可通;则{ 删去栈顶位置; //从路径中删除该通道块若栈不空,则重新测试新的栈顶位置,直至找到一个可通的相邻块或出栈至栈空}}while(栈不空);3、数据结构设计考虑1) 创建一个Int类型的二维数组Maze(i,j),用来存放0和1 ;创建一个堆栈,用来存储当前路径2) 创造一个栈包括(*top表示栈顶,*base表示栈基址,stackSize表示栈容量)堆栈中每个空间包括(ord表示当前位置在路径上的序号,seat表示当前坐标,di表示往下一坐标的方向)当前坐标包括(r表示行,c表示列)4、主要采取三大模块:主程序模块、栈模块和迷宫模块算法设计一、栈模块:实现迷宫数据的抽象化和对迷宫数据的处理。
迷宫问题的求解(回溯法、深度优先遍历、广度优先遍历)

迷宫问题的求解(回溯法、深度优先遍历、⼴度优先遍历)⼀、问题介绍 有⼀个迷宫地图,有⼀些可达的位置,也有⼀些不可达的位置(障碍、墙壁、边界)。
从⼀个位置到下⼀个位置只能通过向上(或者向右、或者向下、或者向左)⾛⼀步来实现,从起点出发,如何找到⼀条到达终点的通路。
本⽂将⽤两种不同的解决思路,四种具体实现来求解迷宫问题。
⽤⼆维矩阵来模拟迷宫地图,1代表该位置不可达,0代表该位置可达。
每⾛过⼀个位置就将地图的对应位置标记,以免重复。
找到通路后打印每⼀步的坐标,最终到达终点位置。
封装了点Dot,以及深度优先遍历⽤到的Block,⼴度优先遍历⽤到的WideBlock。
private int[][] map = { //迷宫地图,1代表墙壁,0代表通路{1,1,1,1,1,1,1,1,1,1},{1,0,0,1,0,0,0,1,0,1},{1,0,0,1,0,0,0,1,0,1},{1,0,0,0,0,1,1,0,0,1},{1,0,1,1,1,0,0,0,0,1},{1,0,0,0,1,0,0,0,0,1},{1,0,1,0,0,0,1,0,0,1},{1,0,1,1,1,0,1,1,0,1},{1,1,0,0,0,0,0,0,0,1},{1,1,1,1,1,1,1,1,1,1}};private int mapX = map.length - 1; //地图xy边界private int mapY = map[0].length - 1;private int startX = 1; //起点private int startY = 1;private int endX = mapX - 1; //终点private int endY = mapY - 1; //内部类,封装⼀个点public class Dot{private int x; //⾏标private int y; //列标public Dot(int x , int y) {this.x = x;this.y = y;}public int getX(){return x;}public int getY(){return y;}}//内部类,封装⾛过的每⼀个点,⾃带⽅向public class Block extends Dot{private int dir; //⽅向,1向上,2向右,3向下,4向左public Block(int x , int y) {super(x , y);dir = 1;}public int getDir(){return dir;}public void changeDir(){dir++;}}/*⼴度优先遍历⽤到的数据结构,它需要⼀个指向⽗节点的索引*/public class WideBlock extends Dot{private WideBlock parent;public WideBlock(int x , int y , WideBlock p){super(x , y);parent = p;}public WideBlock getParent(){return parent;}}⼆、回溯法 思路:从每⼀个位置出发,下⼀步都有四种选择(上右下左),先选择⼀个⽅向,如果该⽅向能够⾛下去,那么就往这个⽅向⾛,当前位置切换为下⼀个位置。
迷宫问题的求解与优化

[课程设计题二]
迷宫问题的求解与优化
[问题描述]
以回溯方法(试探法)和图的广度优先搜索法(路径最短的最优解)求解迷宫的路径,并以图形界面动画的步进方式显示,如下图为回溯方法得到的一个解。
老鼠有四个试探方向。
搜索的回溯算法可以使用栈结构(也可以应用递归)来求解,求最优解就是按图的广度优先搜索求最短路径,两者分开进行。
算法的每一步搜索动作应与界面的变化相协调。
[基本要求]
迷宫的状态可以有几种构造方法,固定的、随机的和人工手动的;也可以用人工方式对固定或随机的方案进行局部的修改。
搜索的动作快慢应能加以调节。
[测试数据]
可先以大小为20*20的迷宫(四周是围墙)进行测试,固定形态的迷宫应包括最终走通和走不通的各种情况;然后测试随机形态的迷宫,再测试人工布局的迷宫。
最后测试大尺寸的迷宫。
[实现提示]
回溯搜索算法可参阅《数据结构》P50,最短路径的算法可参阅《数据结构及应用算法教程》P162。
界面的动作和搜索的单步操作可分别调试完成,最后再通过彼此发消息的方式合成。
迷宫的每一个小单元、老鼠、入点、出点和记载走通的黄色单元格可考虑使用小位图来实现。
最终的图形界面建议如下,如迷宫较大可考虑使用滚动条。
[问题讨论]
迷宫分四方向问题和八方向问题之分,可在解决四方向问题后,再解八方向问题。
迷宫的求解

课程设计的名称:迷宫的求解问题1. 问题描述:迷宫只有两个门,一个叫做入口,另一个叫做出口。
把一只老鼠从一个无顶盖的大盒子的入口处赶进迷宫。
迷宫中设置很多隔壁,对前进方向形成了多处障碍,在迷宫的唯一出口处放置了一块奶酪,吸引老鼠在迷宫中寻找通路以到达出口。
求解迷宫问题,即找出从入口到出口的路径。
2. 基本要求:(1)首先建立一个表示迷宫的数据结构;(2)要有试探方向和栈的设计;(3)不能重复到达某点,不能发生死循环;3. 算法思想:若当前位置可通,则纳入路径,继续前进;若当前位置不可通,则后退,换方向继续探索;若四周均无通路,则将当前位置从路径中删去。
4. 模块划分:(1)int maze[n1][n2]是首先建立一个迷宫的矩阵,0为通路,1为不通。
(2)main()函数将初始化top[],使得所有的开始方向为左。
(3)采用回溯法不断地试探并且及时的纠正错误,使得能够找到正确的路径。
5.数据结构(1)坐标点的结构定义如下:typedef struct node{int x;int y;int c;}linkstack;(2)迷宫的数据结构定义如下:maze[m][n]maze[i][j]=0 通路maze[i][j]=1 不通6. 源程序:#include<stdio.h>#include<stdlib.h>#define n1 10#define n2 10typedef struct node{int x;//存x坐标int y;//存y坐标int c;//存该点可能的下点所在的方向,1表示向右,2向上,3向左,4向右}linkstack;linkstack top[100];//迷宫矩阵int maze[n1][n2]={1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,1,1,1,0,1,0,0,0,1,0,1,1,0,0,0,0,1,1,0,0,1,1,0,1,1,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,1,0,0,1,1,0,1,1,1,0,1,1,0,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,};int i,j,k,m=0;main(){//初始化top[],置所有方向数向左for(i=0;i<n1*n2;i++){top[i].c=1;}printf("the maze is:\n");//打印原始迷宫矩阵for(i=0;i<n1;i++){for(j=0;j<n2;j++)printf(maze[i][j]?"*":"");printf("\n");}i=0;top[i].x=1;top[i].y=0;maze[1][0]=2;//回溯算法do{if(top[i].c<5)//还可以向前试探{if(top[i].x==5&&top[i].y==9)//已经找到一个组合{//打印路径printf("The way %d is:\n",m++);for(j=0;j<=i;j++){printf("(%d,%d)-->",top[j].x,top[j].y);}printf("\n");//打印选出路径的迷宫for(j=0;j<n1;j++){for(k=0;k<n2;k++){if(maze[j][k]==0)printf("");else if(maze[j][k]==2)printf("0");else printf("*");}printf("\n"); }maze[top[i].x][top[i].y]=0;top[i].c=1;i--;top[i].c+=1;continue; }switch(top[i].c)//向前试探{case 1:{if(maze[top[i].x][top[i].y+1]==0){i++;top[i].x=top[i-1].x;top[i].y=top[i-1].y+1;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break; }case 2:{if(maze[top[i].x-1][top[i].y]==0){i++;top[i].x=top[i-1].x-1;top[i].y=top[i-1].y;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break;}case 3:{if(maze[top[i].x][top[i].y-1]==0){i++;top[i].x=top[i-1].x;top[i].y=top[i-1].y-1;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break;}case 4:{if( maze[top[i].x+1][top[i].y]==0){i++;top[i].x=top[i-1].x+1;top[i].y=top[i-1].y;maze[top[i].x][top[i].y]=2;}else{top[i].c+=1;}break;}}}else//回溯{if(i==0)return 0;//已经找完所有解maze[top[i].x][top[i].y]=0;top[i].c=1;i--;top[i].c+=1;}}while(1);}7. 测试情况:截图:结果分析:通过程序运行的结果可以看出,此程序能够实现在有一个入口一个出口的情况下选择路径的功能,并且就此程序而言,有多条路径可以选择。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
迷宫求解问题摘要:用矩阵表示迷宫,将矩阵表示的迷宫转换成无向图,用邻接表存储。
对无向图从入口结点开始广度优先搜索,用一个一维数组存储各个结点的前驱结点的编号,通过出口结点Vn找到其前驱结点Vn-1,再通过Vn-1找到Vn-2,依次类推直到找到出口结点。
关键字:矩阵迷宫求解一、需求分析1.程序题目:迷宫求解问题。
迷宫是一个如下所示的m行n列的0-1矩阵,0表示无障碍,1表示有障碍。
设入口为(1,1),出口为(m,n),每次移动只能从一个无障碍的单元移到周围8个方向的任意一个无障碍的单元,编写程序给出一条通过迷宫的路径或者报告一个“无法通过”的信息。
入口->(0,0,0,1,0,0,0,1,0,0,0,1,0,0,1)(0,1,0,0,0,1,0,1,0,0,0,1,1,1,1)(0,1,1,1,1,1,0,1,0,0,1,1,1,0,1)(1,1,0,0,0,1,1,0,1,1,0,0,1,0,1)(1,0,0,1,0,1,1,1,1,0,1,0,1,0,1)(1,0,1,0,0,1,0,1,0,1,0,1,0,1,0)(1,0,1,1,1,1,1,0,0,1,1,1,1,0,0)(1,1,1,0,1,1,1,1,0,1,0,1,0,1,0)(1,0,1,0,1,0,1,1,1,0,1,0,0,0,1)(0,1,0,1,0,1,0,0,0,1,1,0,0,1,0)->出口2.程序说明及任务:迷宫问题要求寻找一条从入口到出口的路径。
路径是由一组位置构成的,每个位置上都没有障碍,且每个位置(第一个除外)都是前一个位置的东、南、西或北的邻居,如图C。
计算机走迷宫的方法是,采取一步一步试探的方法。
每一步都从东开始,按顺时针对8个方向进行试探,若某方向上maze(x,y)=0,表示可以通行,则走一步;若maze(x,y)=1,表示不可以通行,须换方向再试,直到8个方向都试过;若maze (x,y)均为1,说明此步已无路可走,需退回一步,在上一步的下一个方向重新开始探测。
为此,需设置一个栈,用于记录所走过的位置和方向(i,j,dir)。
当退回一步时,从栈中退出一个元素,以便在上一个位置的下一个方向上探测,如又找到一个行进方向,则把当前位置和方向重新进栈,并走到新的位置。
若探测到位置(m,n),则已经到达迷宫的出口,可以停止探测,输出存在栈中的路径;如果在某一位置的8个方向上堵塞,则退回一步,继续探测;如果已退到迷宫的入口(栈中无元素),则表示此迷宫无路径可走。
二、概要设计主要思想:1. 用矩阵表示的迷宫;2. 将矩阵表示的迷宫转换成无向图,用邻接表存储;3. 对无向图从入口结点开始广度优先搜索;4. 用一个一维数组存储各个结点的前驱结点的编号;5. 通过出口结点Vn找到其前驱结点Vn-1,再通过Vn-1找到Vn-2;6. 依次类推直到找到出口结点。
基本设计算法:1. 设置数组maze[MAX][MAX]来模拟迷宫,2. maze [i][j]=0表示该方格所在的位置可通行, A[i][j]=1则表明该位置不能通行;3. 定义无向图G,迷宫的规格(行、列)存放在G.rownum、G.colnum中,其结点数同迷宫(数组maze [MAX][MAX])的方格个数。
4. 每一个结点的邻接结点为其相邻(从点在数组maze [][]中所处的位置的角度)的八个点中值为0的点,按结点的顺序依次找出每一个点的邻接点,此即完成迷宫图的数组表示转化为无向图表示,G用邻接表存储;5. 采用图的广度优先遍历的方法,从入口结点开始遍历,直到碰到出口结点为止。
并设置record数组来记录结点i在广度优先遍历过程中的前驱结点的编号record[i];6. 这样(record[i],i)表示存在从结点record[i]到i的边,这样就可以从出口顶点在图中的编号回溯出口顶点,如此,一条从入口到出口的最短路径就找到了。
在定义record数组是将所有初始值设为-1,只是为了判断是否存在从入口到出口的路径,因为如果出口结点i的record[i]值为-1则表明遍历过程没有找到出口,也就是说此迷宫无解.7. 反之record[i]!= -1,则此迷宫一定是有解的,因为只有遍历过程中找到了出口I,才会改变record[i]的值,而这个改变后的值是不可能为-1的;8. 输出从入口到出口的路径,用回溯法,只需将图中结点的编号换算成数组maze的坐标即可。
三、详细设计1. 基本过程的算法:设定a[0][0]为入口位置;do{若当前位置可通,则{将当前位置插入栈顶;若该位置是出口位置,则结束;否则切换当前位置的东邻方块为新的当前位置;}否则,若栈不空且栈顶位置尚有其他方向未经探索,则设定新的当前位置为沿顺时针方向旋转找到的栈顶位置的下一相邻块;若栈不空但栈顶位置的四周均不可通,则{删栈顶位置;若栈不空,则重新测试新的栈顶位置,直到找到一个可通的相邻块或出栈至栈空;}}while(栈不空);#include <malloc.h>2. 函数的调用关系图迷宫存储从A[0][0]开始,包括记录路径的数组record[]也是从0下标开始纪录的,为了使输入和输出的坐标符合习惯,只在输入输出时作了一些改变。
迷宫主要部分转换图示矩阵转化成图的邻接表存储:[i](G.vexs[i].data,G.vexs[i].first)→(adjno,next)[1] (0,first)→(11,NULL)[2] (1,NULL)[3] (1,NULL)……[11](0,first)→(21,next)→(1,NULL)……[59](0,first)→(60,next)→(49,NULL)[60](0,first)→(59,NULL)以入口结点作广度优先遍历的起始结点,知道找到出口结点结束遍历,并用record[i]记录遍历的结点i的前驱结点record[i],然后用回溯法输出路径(路径换算成坐标形式)即可。
3.抽象数据类型定义描述① ADT T isData当前位置的行坐标、当前位置的列坐标、走到下一位置的方向end ADT T② ADT Linknode isData数据域、指针域OperationLinknode //构造函数用于构造结点end ADT LinkNode③ ADT Stack isData栈顶指针OperationStack //构造函数输入:无初始化栈:置空栈~stack //析构函数 Push输入:要进栈的项e前置条件:无动作:把e压入栈顶输出:无后置条件:栈顶增加了一个新结点,栈顶指针指向新结点 Pop输入:无前置条件:栈非空动作:弹出栈顶元素输出:返回栈顶元素的值后置条件:删除栈顶元素GetPop动作:返回栈顶元素的值Clear动作:清空栈empty动作: 检查栈顶指示是否等于NULL输出:栈空时返回1,否则返回0end ADT Stack四、调试分析1)程序将用到的函数及参数:1. 迷宫输入: adjlist input (int maze [][MAX]);2. 迷宫图的图结构(邻接表存储)化: adjlist convert (int maze [][MAX],adjlistG);3. 对图的广度优先遍历: void travgraph(adjlist G,int record[],int entry,int exit);4. 迷宫的解的输出: void output (adjlist G,int record[],int entry,int exit)。
2)算法分析和改进在程序的设计中,总的调试比较顺利。
在找出一些小问题顺利编译成功以后,在测试结果的时候发现程序运行的结果错误。
经过仔细的检查,发现程序中8个if语句中的算法出现错误。
导致运行时搜索的方向发生错误。
在if语句中的”i-1<G.colnum&&j+1<G.colnum”转换为”i-1>=0&&j+1<G.colnum”后,错误解除。
经过测试结果,结果正确。
虽然程序能够编译成功,但是还有2个警告项存在.winTC提示警告:success.c 126 :不可移动的指针(地址常数)转换在travgraph 函数中。
success.c 132 :不可移动的指针(地址常数)转换在travgraph 函数中。
经过改进,问题成功解决。
警告消失。
对于不能显示汉语的TC,最后将中文转换为英文,唯一不足的是(*,*)在显示的时候是乱码。
未能几时改进。
3)体会:要能很好的掌握编程,仅仅通过几个简单的程序的编写是无法达成的,更需要大量积累和深入才有可能。
就从这个迷宫的问题来说,在迷宫图向图结构的转化时,对图可用广度优先搜索的算法来解决两点间路径问题。
在程序的编写中也不能一味得向已有的程序进行模仿,而要自己去摸索,去寻求最好的解决方式,只有带着问题去反复进行实践,才能更熟练的掌握和运用,当然,对现有的程序也要多去接触,因为有些程序是我们无法在短时间内想出来的。
最重要的一点就是要持之以恒,要经常性的复习原来所接触的程序,这样才能保证我们有足够的经验去面对程序问题。
五、测试结果:1.运行出现“Please input the length of the maze”字样,“rownum”表示输入”行数”“colnum”表示输入”列数”。
2.然后会出现“Input the 1 row”这时输入数组的第一行,后面的依次类推。
3.数组输入完毕后,会出现” Inputting the maze entrance sits the mark(*,*)”即输入起点坐标。
然后会出现”Inputting the maze exports to sit the mark (*,*)”要求输入出口坐标。
4.点击回车运行所求的路径即会显示出来。
所示输入迷宫大小:行数(<=15):10 [↙]列数(<=15):15[↙]0表示可通行,1表示不能通过。
输入第1行:[1] 00010001000100 1输入第2行:[2] 01000101000111 1 输入第3行:[3] 01111101001110 1 输入第4行:[4] 11000110110010 1 输入第5行:[5] 10010111101010 1 输入第6行:[6] 101001010101010 输入第7行:[7] 101111100111100 输入第8行:[8] 111011********* 输入第9行:[9] 10101011101000 1 输入第10行:[10] 010101000110010 输入入口坐标(*,*):1,1输入出口坐标(*,*):10,15附录1.存储结构:邻接表存储存储2.基本过程的算法:(1). 栈初始化;(2). 将入口点坐标及到达该点的方向(设为-1)入栈;(3). while(栈不空时){ 栈顶元素元素(x,y,d)出栈;求出下一个要试探的方向d++;while (还有剩余试探方向时){ if(d方向可走)则{ (x,y,d)入栈;求新点坐标(i,j);将新点(i,j)切换为当前点(x,y);if ((x,y)= = (n,n))结束;else d=0;}else d++; }}3.源程序:#include <stdio.h> #define MAX 15#define NULL 0 typedef struct listnodestruct listnode *next;}listnode;typedef struct{int data;listnode *first;}headnode;typedef struct {headnode vexs[MAX*MAX]; int vexnum;int rownum;int colnum;}adjlist;/*输入迷宫,0为可通行,1为不可通行,用二维矩阵表示*/adjlist input (int maze[][MAX],adjlist G){int i,j;int rownum,colnum;printf("Please input the length of the maze:\n");printf("rownum=");scanf("%d",&G.rownum);printf("colnum=");scanf("%d",&G.colnum);for(i=0;i<G.rownum;i++){printf("Input the %d row:[%d] ",i+1,i+1);for(j=0;j<G.colnum;j++)scanf("%d",&maze[i][j]);}return(G);}/*二维数组向无向图的转化*/adjlist change (int maze[][MAX],adjlist G){int i,j;listnode *p;G.vexnum=G.rownum*G.colnum;for(i=0;i<G.vexnum;i++) /*图中结点的初始化*/ {G.vexs[i].data=maze[i/G.colnum][i%G.colnum];G.vexs[i].first=NULL;}for(i=0;i<G.rownum;i++) /*将无向边用指针表示出来*/ for(j=0;j<G.colnum;j++){if(i-1>=0&&maze[i-1][j]==0){p=(listnode *)malloc(sizeof(listnode));p->adjno=(i-1)*G.colnum+j;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i+1<G.rownum&&maze[i+1][j]==0){p=(listnode *)malloc(sizeof(listnode));p->adjno=(i+1)*G.colnum+j;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(j-1>=0&&maze[i][j-1]==0){p=(listnode *)malloc(sizeof(listnode)); p->adjno=i*G.colnum+j-1;p->next=G.vexs[i*G.colnum+j].first; G.vexs[i*G.colnum+j].first=p;}if(j+1<G.colnum&&maze[i][j+1]==0){p=(listnode *)malloc(sizeof(listnode)); p->adjno=i*G.colnum+j+1;p->next=G.vexs[i*G.colnum+j].first; G.vexs[i*G.colnum+j].first=p;}if(i-1>=0&&j-1>=0&&maze[i-1][j-1]==0) {p=(listnode *)malloc(sizeof(listnode)); p->adjno=(i-1)*G.colnum+j-1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i-1>=0&&j+1<G.colnum&&maze[i-1][j+1]==0) {p=(listnode *)malloc(sizeof(listnode));p->adjno=(i-1)*G.colnum+j+1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i+1<G.colnum&&j-1>=0&&maze[i+1][j-1]==0) {p=(listnode *)malloc(sizeof(listnode));p->adjno=(i+1)*G.colnum+j-1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}if(i+1<G.colnum&&j+1<G.colnum&&maze[i+1][j+1]==0){p=(listnode *)malloc(sizeof(listnode));p->adjno=(i+1)*G.colnum+j+1;p->next=G.vexs[i*G.colnum+j].first;G.vexs[i*G.colnum+j].first=p;}}return(G);}/* 用int travgraph()函数广度优先遍历无向图*/int travgraph(adjlist G,int record[],int entry,int exit){listnode *p;int queue[MAX*MAX],visited[MAX*MAX]; /*用visited[]数组标记图的结点是否遍历过*/int i;int front=0,rear=1;for(i=0;i<G.rownum*G.colnum;i++){record[i]=-1;/*置record[i]为-1,以便检查从入口到出口结点V[n]有无通路*/visited[i]=0;}visited[entry]=1;queue[rear]=entry;while(front!=rear) /*记录遍历路径,(record[i],i)表示存在从结点record[i]到i的边*/{p=G.vexs[queue[front+1]].first;while(p!=NULL){if(visited[p->adjno]==0){visited[p->adjno]=1;record[p->adjno]=queue[front+1];queue[++rear]=p->adjno;if(p->adjno==exit)goto end;}p=p->next;}front=front+1;}end:;}/*用回溯法找到从出口到入口的路径,并输出*/ void output (int record[],int entry,int exit) {int i=0,t;if(entry==exit&&G.vexs[exit].data==0)printf("It's already at export\n");elseif(record[exit]!=-1){t=exit;{printf("The most short path is as follows:\n");while(t!=entry){printf("[%d,%d]<-",t/G.colnum+1,t%G.colnum+1); t=record[t];if(++i%5==0)printf("\n");}printf("[%d,%d]",t/G.colnum+1,t%G.colnum+1);}}elseprintf("Have no path from the entrance to the exit\n");}void main(){int entry_row,entry_col,exit_row,exit_col,entry,exit;int maze[MAX][MAX];int record[MAX*MAX];G=input(maze,G);G=change(maze,G);printf("Inputting the maze entrance sits the mark(*,*):"); scanf("%d,%d",&entry_row,&entry_col);printf("Inputting the maze exports to sit the mark(*,*):"); scanf("%d,%d",&exit_row,&exit_col);entry=--entry_row*G.colnum+--entry_col;exit=--exit_row*G.colnum+--exit_col;travgraph(G,record,entry,exit);output(record,entry,exit);getch();}4.测试数据和结果输入:行数(<=15):10 [↙]列数(<=15):15[↙]0表示可通行,1表示不能通过。