栈的应用——迷宫问题

一、实验目的

(本次实验所涉及并要求掌握的知识点)

       掌握顺序栈和循环队列的存储表示和运算的实现,并运用基本运算完成复杂的功能

二、实验内容与设计思想

(设计思路、主要数据结构、主要代码结构、主要代码段分析)

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

  1. 定义迷宫的数据结构:首先需要定义迷宫的数据结构,通常可以使用一个二维数组来表示迷宫的格子。迷宫的每个格子可以是墙壁或者通道,可以用不同的值来表示。
  2. 初始化栈:创建一个栈数据结构用于存储路径方块。
  3. 初始化起点:将起点的坐标入栈,并将起点设置为不可访问状态。
  4. 迷宫路径搜索:使用回溯算法,在迷宫中寻找路径。具体步骤如下:
    • 检查栈是否为空,如果为空表示没有找到路径,搜索结束。
    • 获取栈顶元素,包括方块的坐标和方向。
    • 判断当前方块是否为终点,如果是则找到一条路径,打印路径并结束搜索。
    • 在当前方块的相邻方块中选择一个可访问的方块,并将其入栈。
    • 将选中的方块设置为不可访问状态,表示已经访问过。
    • 如果当前方块没有可访问的相邻方块,则将当前方块出栈,并将其设置为可访问状态。
    • 重复上述步骤直到找到路径或者搜索结束。
  5. 打印路径:找到路径后,可以通过遍历栈来获取路径的方块坐标,然后按照指定格式打印出路径信息。
  6. 销毁栈:在搜索结束后,需要释放栈的内存空间。

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值