一、实验目的
(本次实验所涉及并要求掌握的知识点)
掌握顺序栈和循环队列的存储表示和运算的实现,并运用基本运算完成复杂的功能
二、实验内容与设计思想
(设计思路、主要数据结构、主要代码结构、主要代码段分析)
1. 实验内容
内容:
1.编写一个程序,改进教材P93求解迷宫问题程序(见P95),要求输出下图所示迷宫的所有路径,并求第一条最短路径长度及最短路径
0 1 2 3 4 5
0 |_||_||_||_||_||_|
1 |_| |_|
2 |_| |_| |_|
3 |_| |_||_|
4 |_||_| |_|
5 |_||_||_||_||_||_|
(1,1)为入口,(4,4)为出口。
输出迷宫中所有从“入口”到“出口”的路径。
2. 抽象数据类型定义
内容1:
ADT set
{
数据对象:迷宫,栈
数据关系:迷宫和栈之间的关系是栈用于存储迷宫路径的方块。
基本运算:
void InitStack(StType*& s); // 初始化栈
void DestroyStack(StType*& s); // 销毁栈
bool StackEmpty(StType* s); // 判断栈是否为空
bool Push(StType*& s, Box e); // 入栈
bool Pop(StType*& s, Box& e); // 出栈
bool GetTop(StType* s, Box& e); // 获取栈顶元素
void PrintPath(StType* st, int pathLength); // 打印路径
void dispaths(StType* st, int pathCount); // 显示所有路径
void dispminpath(StType* st); // 显示最短路径
bool mgpath(int xi, int yi, int xe, int ye); // 寻找迷宫路径
}
3. 设计思路
内容1:
- 定义迷宫的数据结构:首先需要定义迷宫的数据结构,通常可以使用一个二维数组来表示迷宫的格子。迷宫的每个格子可以是墙壁或者通道,可以用不同的值来表示。
- 初始化栈:创建一个栈数据结构用于存储路径方块。
- 初始化起点:将起点的坐标入栈,并将起点设置为不可访问状态。
- 迷宫路径搜索:使用回溯算法,在迷宫中寻找路径。具体步骤如下:
- 检查栈是否为空,如果为空表示没有找到路径,搜索结束。
- 获取栈顶元素,包括方块的坐标和方向。
- 判断当前方块是否为终点,如果是则找到一条路径,打印路径并结束搜索。
- 在当前方块的相邻方块中选择一个可访问的方块,并将其入栈。
- 将选中的方块设置为不可访问状态,表示已经访问过。
- 如果当前方块没有可访问的相邻方块,则将当前方块出栈,并将其设置为可访问状态。
- 重复上述步骤直到找到路径或者搜索结束。
- 打印路径:找到路径后,可以通过遍历栈来获取路径的方块坐标,然后按照指定格式打印出路径信息。
- 销毁栈:在搜索结束后,需要释放栈的内存空间。
4. 数据结构定义
#define M 6
#define N 7
#define MaxSize 100
typedef struct {
int i, j; // 迷宫中的位置坐标
int di; // 下一相邻方块的方位
} Box; // 表示迷宫中的一个方块
typedef struct {
Box data[MaxSize]; // 存储迷宫路径的数组
int top; // 栈顶指针
} StType; // 栈类型
void InitStack(StType*& s); // 初始化栈
void DestroyStack(StType*& s); // 销毁栈
bool StackEmpty(StType* s); // 判断栈是否为空
bool Push(StType*& s, Box e); // 入栈
bool Pop(StType*& s, Box& e); // 出栈
bool GetTop(StType* s, Box& e); // 获取栈顶元素
void PrintPath(StType* st, int pathLength); // 打印路径
void dispaths(StType* st, int pathCount); // 显示所有路径
void dispminpath(StType* st); // 显示最短路径
bool mgpath(int xi, int yi, int xe, int ye); // 寻找迷宫路径
5. 程序中各函数调用关系
主函数:
mgpath() : 寻找迷宫路径
InitStack() : 初始化栈
Push() : 元素入栈
Pop() : 元素出栈
GetTop() : 获取栈顶元素
StackEmpty() : 判断栈是否为空
dispaths() : 显示所有路径
DestroyStack() : 销毁栈
三、实验步骤和调试过程
(实验步骤、测试数据设计、测试结果分析)
1. 测试数据
内容1:
起点:(1,1)
终点:(4,4)
2. 程序运行结果截图
内容1:
附录代码:
//maze.h
#define M 6
#define N 6
#define MaxSize 100
typedef struct {
int i, j; // 迷宫中的位置坐标
int di; // 下一相邻方块的方位
} Box; // 表示迷宫中的一个方块
typedef struct {
Box data[MaxSize]; // 存储迷宫路径的数组
int top; // 栈顶指针
} StType; // 栈类型
void InitStack(StType*& s); // 初始化栈
void DestroyStack(StType*& s); // 销毁栈
bool StackEmpty(StType* s); // 判断栈是否为空
bool Push(StType*& s, Box e); // 入栈
bool Pop(StType*& s, Box& e); // 出栈
bool GetTop(StType* s, Box& e); // 获取栈顶元素
void dispaths(StType* st, int pathCount); // 显示所有路径
bool mgpath(int xi, int yi, int xe, int ye); // 寻找迷宫路径
//maze.c
#include <stdio.h>
#include <malloc.h>
#include "maze.h"
int mg[M + 2][N + 2] = {
{1, 1, 1, 1, 1, 1, 1}, // 迷宫数组,用于表示迷宫的墙壁和路径
{1, 0, 0, 0, 0, 0, 1},
{1, 0, 1, 0, 0, 0, 1},
{1, 0, 0, 1, 1, 0, 1},
{1, 1, 0, 0, 0, 0, 1},
{1, 1, 1, 1, 1, 1, 1}
};
// 初始化栈
void InitStack(StType*& s) {
s = (StType*)malloc(sizeof(StType));
s->top = -1; // 栈顶指针初始化为-1
}
// 销毁栈
void DestroyStack(StType*& s) {
free(s); // 释放栈所占内存空间
}
// 判断栈是否为空
bool StackEmpty(StType* s) {
return (s->top == -1); // 栈顶指针为-1表示栈为空
}
// 元素入栈
bool Push(StType*& s, Box e) {
if (s->top == MaxSize - 1)
return false; // 栈已满,无法入栈
s->top++; // 栈顶指针加1
s->data[s->top] = e; // 将元素e压入栈顶
return true; // 入栈成功
}
// 元素出栈
bool Pop(StType*& s, Box& e) {
if (s->top == -1)
return false; // 栈为空,无法出栈
e = s->data[s->top]; // 弹出栈顶元素,赋值给e
s->top--; // 栈顶指针减1
return true; // 出栈成功
}
// 获取栈顶元素
bool GetTop(StType* s, Box& e) {
if (s->top == -1)
return false; // 栈为空,无法获取栈顶元素
e = s->data[s->top]; // 将栈顶元素赋值给e
return true; // 获取栈顶元素成功
}
// 显示所有路径
void dispaths(StType* st, int pathCount) {
Box path[MaxSize];
int k = 0;
int pathLength = 0;
while (!StackEmpty(st)) {
Pop(st, path[k]);
k++;
pathLength++;
}
printf("路径长度:%d\n", pathLength);
printf("路径为:");
for (int i = k - 1; i >= 0; i--) {
printf("(%d,%d) ", path[i].i, path[i].j);
if ((i + 1) % 5 == 0)
printf("\n"); // 每行打印5个方块的路径坐标,换行显示
}
printf("\n");
}
// 寻找迷宫路径
bool mgpath(int xi, int yi, int xe, int ye) {
StType* st;
InitStack(st); // 初始化栈
Box e;
int i, j, di, i1, j1;
bool find;
e.i = xi;
e.j = yi;
e.di = -1;
Push(st, e); // 起点入栈
mg[xi][yi] = -1; // 将起点设置为不可访问状态
while (!StackEmpty(st)) {
GetTop(st, e);
i = e.i;
j = e.j;
di = e.di;
if (i == xe && j == ye) {
printf("一条迷宫路径如下:\n");
dispaths(st, 0); // 打印找到的迷宫路径
DestroyStack(st); // 销毁栈
return true;
}
find = false;
while (di < 4 && !find) {
di++;
switch (di) {
case 0:
i1 = i - 1;
j1 = j;
break;
case 1:
i1 = i;
j1 = j + 1;
break;
case 2:
i1 = i + 1;
j1 = j;
break;
case 3:
i1 = i;
j1 = j - 1;
break;
}
if (mg[i1][j1] == 0) {
find = true; // 找到相邻的可访问方块
}
}
if (find) {
st->data[st->top].di = di; // 更新栈顶元素的方位
e.i = i1;
e.j = j1;
e.di = -1;
Push(st, e); // 将相邻方块入栈
mg[i1][j1] = -1; // 将相邻方块设置为不可访问状态
}
else {
Pop(st, e); // 栈顶元素出栈
mg[e.i][e.j] = 0; // 将出栈的方块设置为可访问状态
}
}
DestroyStack(st); // 销毁栈
return false; // 未找到迷宫路径
}
//mian.c
#include <stdio.h>
#include <stdlib.h>
#include "maze.h"
int main() {
int xi, yi, xe, ye;
printf("请输入起点坐标(xi, yi):");
scanf("%d %d", &xi, &yi);
printf("请输入终点坐标(xe, ye):");
scanf("%d %d", &xe, &ye);
if (mgpath(xi, yi, xe, ye)) {
printf("找到一条迷宫路径。\n");
}
else {
printf("未找到迷宫路径。\n");
}
return 0;
}