数据结构实验:用栈求解迷宫问题的所有路径及最短路径

用栈求解迷宫问题的所有路径及最短路径

题目描述

编写一个程序exp3-5.cpp,改进《教程》3.1.4节中的求解迷宫问题程序,要求输

如图3.9所示的迷宫的所有路径,并求第一条最短路径及其长度。

在本实验中用mg作为迷宫数组,用St数组作为顺序栈,Path数组保存一条迷宫径,将它们都设置为全局变量。
功能算法如下:

· mgpath(int xi,int yi,int xe,int ye):求解迷宫问题,即输出从入口(xi,yi)到出口(xe,ye)的全部路径和最短路径(包含最短路径长度)。与《教程》3.1.4节中的求解迷宫问题程序相比,其改进的方法是当找到一条路径时不使用return语句退出,而是出栈一次,重新回溯走另一条路径并输出,并用minlen记录最短路径长度,用Path数组记录最短路径。

· dispapath():输出一条路径并求最短路径。

· dispminpath():输出第一条最短路径及其长度。

运行代码

cpp 复制代码
#include<stdio.h>
#define M 4
#define N 4
#define MaxSize 100
// 定义迷宫数组
int mg[M + 2][N + 2] = {
    {1,1,1,1,1,1},{1,0,0,0,1,1}, { 1,0,1,0,0,1 },
    {1,0,0,0,1,1},{1,1,0,0,0,1},{ 1,1,1,1,1,1 } };
// 定义结构体表示路径中的位置和方向
struct {
    int i, j;
    int di;
} St[MaxSize], Path[MaxSize];//定义栈和存放最短路径的数组
int top = -1;                //栈顶指针
int count = 1;               //路径数计数
int minlen = MaxSize;        //最短路径长度
// 输出一条路径并求最短路径
void dispapath()
{
    int k;
    // 输出第 count 条路经
    printf("%5d:", count++);
    for (k = 0; k <= top; k++)
    {
        // 输出路径中的每个位置
        printf("(%d,%d)", St[k].i, St[k].j);
    }
    printf("\n");
    if (top + 1 < minlen)    //比较最短路径
    {
        for (int k = 0; k <= top; k++)
        {
            // 将当前路径复制到最短路径数组中
            Path[k] = St[k];
        }
        minlen = top + 1;
    }
}
// 输出最短路径
void dispminpath()
{
    printf("最短路径如下:\n");
    // 输出最短路径长度
    printf("长度:%d\n", minlen);
    printf("路径:");
    for (int k = 0; k < minlen; k++)
    {
        // 输出最短路径中的每个位置
        printf("(%d,%d)", Path[k].i, Path[k].j);
    }
    printf("\n");
}
// 寻找迷宫路径
void mgpath(int xi, int yi, int xe, int ye)
{
    int i, j, i1, j1, di;
    bool find;
    top++;
    St[top].i = xi; // 将起始位置压入栈
    St[top].j = yi;
    St[top].di = -1;
    mg[xi][yi] = -1;
    while (top > -1)
    {
        i = St[top].i; j = St[top].j;
        di = St[top].di;
        if (i == xe && j == ye)
        {        
            dispapath(); // 输出当前路径并更新最短路径相关信息
            mg[i][j] = 0;
            top--;
            i = St[top].i; j = St[top].j;
            di = St[top].di;
        }
        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[top].di = di;
            top++;
            St[top].i = i1; St[top].j = j1;
            St[top].di = -1;
            mg[i1][j1] = -1;
        }
        else
        {
            mg[i][j] = 0;
            top--;
        }
    }
       dispminpath(); // 输出最短路径
}
int main()
{
    printf("迷宫所有列途径如下:\n");
    // 从左上角 (1,1) 到右下角 (M,N) 寻找路径
    mgpath(1, 1, M, N);
    return 1;
}

代码思路

一、整体架构

  1. 首先定义了迷宫的大小 MN,以及一个用于存储路径的结构体和两个用于存储路径的数组 StPath。还定义了一些变量用于记录栈顶指针、路径计数和最短路径长度等。
  2. 定义了三个主要函数:dispapath 用于输出一条路径并更新最短路径信息;dispminpath 用于输出最短路径;mgpath 是核心函数,用于在迷宫中寻找路径。
  3. main 函数中调用 mgpath 函数,传入起点和终点坐标,启动路径搜索过程。

二、函数功能详解

  1. mgpath 函数

    • 初始化:将起点坐标压入栈 St,并将起点位置在迷宫数组 mg 中标记为已访问(设为 -1)。
    • 循环搜索:通过一个 while 循环不断探索迷宫,直到栈为空(top > -1)。
      • 检查当前位置是否为终点:如果是终点,调用 dispapath 输出当前路径,并将终点位置在迷宫中重新设为可通行(设为 0),然后调整栈顶指针,准备继续搜索其他路径。
      • 寻找下一个可通行位置:如果当前位置不是终点,通过一个内循环不断尝试四个方向(上、右、下、左),找到下一个可通行位置(值为 0 的位置)。如果找到,更新当前位置的方向,将新位置压入栈,并在迷宫中标记新位置为已访问。如果没有找到可通行位置,将当前位置在迷宫中重新设为可通行,然后调整栈顶指针回退。
    • 输出最短路径:搜索结束后,调用 dispminpath 输出最短路径。
  2. dispapath 函数

    • 输出当前路径编号和路径中的每个位置。
    • 如果当前路径长度小于最短路径长度,将当前路径复制到 Path 数组中,并更新最短路径长度。
  3. dispminpath 函数:输出最短路径的长度和路径中的每个位置。

三、数据结构的运用

  1. 迷宫数组 mg:用于表示迷宫的布局,其中 1 表示墙壁,0 表示可通行的路径。
  2. 结构体和数组:定义了一个结构体表示路径中的位置和方向,使用两个数组 StPath 分别作为栈和存储最短路径的数组。栈用于存储当前正在探索的路径,而 Path 数组用于存储最短路径。

实验小结

一、实验目的与成果

本次实验的目的是在给定的迷宫中找到从起点到终点的路径,并输出所有路径以及最短路径。通过这段代码,成功地实现了以下功能:

  1. 利用深度优先搜索算法,借助栈数据结构对迷宫进行遍历,找到了从起点到终点的所有可能路径。
  2. 输出了所有路径的编号以及路径中的每个位置,清晰地展示了探索过程中的各种路径情况。
  3. 确定并输出了最短路径的长度和具体位置序列,为用户提供了迷宫的最优解。

二、遇到的问题及解决方法

  1. 路径准确性问题

    • 问题表现:在实验过程中,可能会出现输出的路径不准确或者最短路径计算错误的情况。
    • 解决方法:仔细检查代码中的逻辑,特别是在路径长度比较和最短路径更新的部分。确保在判断路径长度和复制路径到最短路径数组时的逻辑正确。同时,检查在探索迷宫过程中对位置的标记和回溯操作是否准确无误。
  2. 边界处理

    • 问题表现:在探索迷宫时,可能会出现数组越界的错误,尤其是在探索新位置时。
    • 解决方法:在代码中添加对新位置的合法性检查,确保新位置在迷宫范围内。在计算不同方向的新位置坐标时,仔细检查是否超出了迷宫的边界,避免出现越界访问的情况。
  3. 路径唯一性和最短路径选择

    • 问题表现:代码可能会找到重复的路径,并且在存在多条最短路径时可能只输出其中一条。
    • 解决方法:可以考虑使用标记数组来记录已经访问过的位置,避免重复探索相同的路径。对于最短路径的输出,可以根据具体需求进行调整,例如输出所有长度相同的最短路径,或者根据特定规则选择其中一条作为最终的最短路径。

三、实验收获与体会

  1. 数据结构与算法的应用:通过这个实验,深入理解了栈在深度优先搜索算法中的重要作用。栈的后进先出特性非常适合记录路径的回溯过程,能够有效地实现迷宫路径的搜索。同时,对深度优先搜索算法的理解也更加深刻,掌握了如何运用该算法解决实际问题。

  2. 问题解决能力:在实验过程中,遇到了各种问题,通过分析问题、调试代码和查阅资料,提高了问题解决能力和编程技巧。学会了如何运用逻辑分析和调试工具来找出代码中的错误,并采取有效的措施进行修复。

  3. 代码优化意识:在解决问题的过程中,意识到代码的性能和可读性可以进一步优化。例如,可以使用更高效的算法来提高搜索效率,或者改进变量命名和添加注释来提高代码的可读性和可维护性。

  4. 团队合作与交流:如果是在团队中进行实验,可以与团队成员进行交流和讨论,分享解决问题的经验和方法。团队合作可以提高实验的效率和质量,同时也可以学习到其他人的编程思路和技巧。

相关推荐
xiaoshiguang32 小时前
LeetCode:222.完全二叉树节点的数量
算法·leetcode
爱吃西瓜的小菜鸡2 小时前
【C语言】判断回文
c语言·学习·算法
别NULL3 小时前
机试题——疯长的草
数据结构·c++·算法
TT哇3 小时前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
ZSYP-S4 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos4 小时前
C++----------函数的调用机制
java·c++·算法
唐叔在学习4 小时前
【唐叔学算法】第21天:超越比较-计数排序、桶排序与基数排序的Java实践及性能剖析
数据结构·算法·排序算法
ALISHENGYA4 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(switch语句)
数据结构·算法
chengooooooo4 小时前
代码随想录训练营第二十七天| 贪心理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和
算法·leetcode·职场和发展
jackiendsc5 小时前
Java的垃圾回收机制介绍、工作原理、算法及分析调优
java·开发语言·算法