栈的简单应用之迷宫老鼠(C++不调库的情况下完美实现,含源码演示)

参考书籍:数据结构、算法与应用:C++语言描述(原书第2版) (美)萨尼

1.问题定义及需求分析

     假设有一个NxM的迷宫,有一个入口,有一个出口。作为程序员你操纵一只老鼠,让它找到一条路径。并将路径输出出来。

输入形式:N M,地图,入口坐标和出口坐标

输出形式:路径

2.概要设计

   用一个动态二维bool数组来初始化这个迷宫,采用STL栈存储路径,数组的二维下标代表路径,故栈的元素采用STL里的pair。之后将栈全部取出存入一个动态数组,循环将动态数组输出。

3.详细设计

   地图存储及初始化:因为只有墙和路两种值,而地图又是确定的,故采用动态的bool数组。值得注意的是,因为边界条件,如果在边界,就不能四面都判断,故在四边上了一堵墙,所以实际空间是(N+2)x(M+2)。(1代表墙,0代表路)

      代码:bool **p=new bool *[n+2];

    for (int i = 0; i <= n+1; ++i)

         p[i] = new bool[m + 2];

    for (int i = 0; i <= m+1; ++i)

    {

         p[0][i] = 1;

         p[n+1][i] = 1;

    }

    for (int i = 1; i < n; ++i)

    {

         p[i][m+1]=p[i][0] = 1;

    }

    for (int i = 1; i <= n; ++i)

         for (int j = 1; j <= m; ++j)

             cin >> p[i][j];

      寻迹:先将起点压入栈,按照深度优先遍历(即每次从栈顶找,不断将可走的节点压入栈,并把该节点的bool值改为1,使它不能再遍历,然后将该节点无路可走,就将元素弹出,如果有路径,则栈最后一定是非空的),出循环条件为到达终点或栈已经空了。

   代码:while (!path.empty()&&now!=pathend)

    {

         if (!p[now.first + 1][now.second])

         {

             p[now.first + 1][now.second] = 1;

             ++now.first;

             path.push(now);

             ++step;

         }

         else if (!p[now.first][now.second+1])

         {

             p[now.first][now.second + 1] = 1;

             ++now.second;

             path.push(now);

             ++step;

         }

         else if (!p[now.first -1][now.second])

         {

             p[now.first - 1][now.second]=1;

             --now.first;

             path.push(now);

             ++step;

         }

         else if (!p[now.first ][now.second-1])

         {

             p[now.first][now.second - 1] = 1;

             --now.second;

             path.push(now);

             ++step;

         }

         else

         {

             --step;

             path.pop();//当前无路可走往回走

         }

    }

4.调试分析:

对所遇问题的解决方法及分析:

主要使用了VS的调试器跟踪寻迹循环,第一次发现bool数组初始化小了,为[n+1]x[m+1]。而不是[n+2]x[m+2];

还有if (!p[now.first + 1][now.second])

         {

             p[now.first + 1][now.second] = 1;

             ++now.first;

             path.push(now);

             ++step;

         }

         else if (!p[now.first][now.second+1])

         {

             p[now.first][now.second + 1] = 1;

             ++now.second;

             path.push(now);

             ++step;

         }

    这语句因为4个都差不多,我就写了一个后面复制了,调试过程中,发现有一个有个地方p的下标没改。

算法的时空分析及改进思想:

时空分析:

因为算法是遍历一个栈,最好情况下是一条路直接走到终点,既不用后退,最长路又铁定小于NxM,所以最好情况是o(n^2)。

最坏情况下,走了很多的死路才到终点,但考虑到对同一个位置最多来的时候走一次,退的时候又走一次所以最多为2xNxM,复杂度是o(n^2)。

实际上,不可能地图每个节点都走,所以会明显好于o(n^2)。

改进思想:

实际在编写不断检验的时候已经做了很多改进,比如入栈的操作,起初是4个if,后来改为了if,else if,即只有当前路走到了死,才去找新的,省去了一些栈的操作。还有考虑程序可读性,又删除了一些多余语句。

经验和体会:

  希望以后自己能大概构思好了程序,再编写。在逻辑上先足够严谨,不要急于求成。细心一些。

5.使用说明and6.测试结果:

   7.附录

void riddle()

{

    int n,m;//迷宫大小

    cout << "请输入迷宫大小:" << endl;

    cin >> n>>m;

    cout << "请输入迷宫:" << endl;

    bool **p=new bool *[n+2];

    for (int i = 0; i <= n+1; ++i)

         p[i] = new bool[m + 2];

    for (int i = 0; i <= m+1; ++i)

    {

         p[0][i] = 1;

         p[n+1][i] = 1;

    }

    for (int i = 1; i < n; ++i)

    {

         p[i][m+1]=p[i][0] = 1;

    }

    for (int i = 1; i <= n; ++i)

         for (int j = 1; j <= m; ++j)

             cin >> p[i][j];//初始化地图

    stack<pair<int, int>> path;//存储路径

    pair<int, int> *paths;//存储栈的数组

    int step = 1;//记录路径长度

    cout << "请输入起点:" << endl;

    pair<int, int> now,pathend;//记录当前位置和终点

    cin >> now.first >> now.second;

    path.push(now);

    p[now.first][now.second] = 1;

    cout << "请输入终点" << endl;

    cin >> pathend.first >> pathend.second;

    while (!path.empty()&&now!=pathend)

    {

         if (!p[now.first + 1][now.second]) //

         {

             p[now.first + 1][now.second] = 1;

             ++now.first;

             path.push(now);

             ++step;

         }

         else if (!p[now.first][now.second+1]) //

         {

             p[now.first][now.second + 1] = 1;

             ++now.second;

             path.push(now);

             ++step;

         }

         else if (!p[now.first -1][now.second]) //

         {

             p[now.first - 1][now.second]=1;

             --now.first;

             path.push(now);

             ++step;

         }

         else if (!p[now.first ][now.second-1]) //

         {

             p[now.first][now.second - 1] = 1;

             --now.second;

             path.push(now);

             ++step;

         }

         else

         {

             --step;

             path.pop();//当前无路可走往回走

         }

    }

    if (path.empty())

    {

         cout << "不存在路径"<<endl;

         return;

    }

    paths = new pair<int, int>[step];

    int i = step;

    while (!path.empty())

    {

         paths[--i] = path.top();//将栈取出

         path.pop();

    }

    cout << "找到路径长度为" << step << "的路径:" << endl;

    for (int i = 0; i < step - 1; ++i)

         cout << '(' << paths[i].first << ',' << paths[i].second << ')' << "->";

    cout << '(' << paths[step-1].first << ',' << paths[step-1].second << ')'  << endl;

    for (int i = 0; i <= n + 1; ++i)

         delete p[i];

    delete p;

    delete paths;

}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值