关于用栈和队列分别解决走迷宫问题的方法讨论(参与者:陈卓,毛敏磊)

这篇具有很好参考价值的文章主要介绍了关于用栈和队列分别解决走迷宫问题的方法讨论(参与者:陈卓,毛敏磊)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

关于用栈和队列分别解决走迷宫问题

对于生活中最常见的小游戏——走迷宫,相信大家都不陌生,人为走相信大家都会走,但能不能用代码实现,我们认为是可以的,以下是我们对如何走迷宫的一些看法和代码实现(cz负责队列解决,mml负责用栈解决)

1.关于用队列解决:

先简单介绍一下队列:队列是一种操作受限的线性表,只允许在表的一端进行插入,在表的另一端进行删除。可进行插入的一段称为队尾,可进行删除的一端称为队头。队列的主要特点就是先进先出。依照存储结构可分为顺序队和链式队。
解决思路1.对于一个迷宫,我们将起点设置为(1,1),终点设置为(M,N),通路为0,不通路为1。对于当前位置我们知道可以往上,下,左,右四个方向行走,我们默认按照上,右,下,左的顺序依次查找可以走的方向,将可以走的方格存入队列中,当四个方向查找完毕后,弹出队首元素从而开始对存入队列中的下一个元素进行可通路查找,当目前的队首元素恰好等于终点坐标时,即为找到终点(M,N)。如果队列已空且还没有找到终点,则该迷宫没有终点。
2.那么到此已经解决了如何找到迷宫出路的大体方法,既然找到,又该如何输出呢?对此,我们认为可以在存储方格坐标的数据类型中加一个用来存储上一方格在队列中的位置下标pre(默认起点下标为"-1"),那么输出路径时就可以通过寻找上一方格的位置下标输出相应队列元素。例如:起点(1,1)的右方向假如是通路,那么存入队列中的元素为(1,2)且该元素pre=0.
3.相信会有人问队列元素不是被弹出了吗,怎么还能输出之前的队列元素?其实这就是队列中顺序队的存储特点:在对顺序队进行操作时弹出元素只是将头位置加1,而并非真正意义上的删除,在这种情况下就能很好的保留之前所存入通路坐标,进而解决迷宫问题,如下图(图片引用自PPT——栈与队列):

关于用栈和队列分别解决走迷宫问题的方法讨论(参与者:陈卓,毛敏磊)

以下是代码的具体实现(队列):

#include<iostream>
#define Maxsize 10000   //定义一个存储数据最大区间
using namespace std;

typedef struct
{
	int x;		//横坐标
	int y;		//纵坐标
	int pre;
}Box2;	//定义一个数据类型存储位置信息

typedef struct
{
	Box2 data[Maxsize];		//队列存储的数据类型
	int front;			//队列头
	int rear;			//队列尾
}Queue;	//定义一个队列,该队列为顺序队列

int mg[1002][1002]; //定义一个存放迷宫的二维数组

void CreateQueue(Queue*& q)
{
	q = new Queue;
	q->front = q->rear = -1;
}	//为新队列申请存储空间

void EnQueue(Queue*& q, Box2 x)
{
	if (q->rear == Maxsize - 1)
	{
		cout << "存储失败!" << endl;
		return;
	}	//判断队列是否已满

	q->rear++;
	q->data[q->rear] = x;

	return;
}	//将新的可通方格存入队列中

void OutQueue(Queue*& q, Box2& x)
{
	if (q->front == q->rear)
	{
		cout << "读取失败!" << endl;
		return;
	}	//判断队列是否为空

	q->front++;
	x = q->data[q->front];

	return;
}

int QueueEmpty(Queue* q)
{
	return (q->front == q->rear);
}	//判断队列是否为空,若为空则返回1,否则返回0

void Cout(Queue* q, int front)
{
	int x = front;
	int i;

	while (x != 0)
       {
	    i = x;
	    x = q->data[x].pre;
	    q->data[i].pre = -1;
       }    //通过循环分别将从终点开始的前一位置记为-1

	x = 0;

	while (x < Maxsize)
	{
		if (q->data[x].pre == -1)
		{
			cout << "( " << q->data[x].x << " , " << q->data[x].y << " )" << endl;
		}
		x++;
	}    //遍历队列,将队列中数据为-1的坐标输出
}

void SearchPath(int x1, int y1, int x2, int y2)
{
	Box2 e;
	Queue *q;
	int i, j;

	CreateQueue(q);

	e.x = x1;
	e.y = y1;
	e.pre = -1;	//由于起点无前一位置,因此将起点前一位置定为-1
	EnQueue(q, e);	//将迷宫起点存入队列中

	mg[x1][y1] = 1;     //将起点值改为1,避免重复进入

	while (!QueueEmpty(q))
	{
		OutQueue(q, e);	//判断队列中下一方格的通路情况

		i = e.x;
		j = e.y;

		if (i == x2 && j == y2)
		{

			Cout(q, q->front);
			delete q;

			return;
		}	//判断该方格是否为终点

		for (int m = 0; m < 4; m++)
		{
			int x, y;
			switch (m)
			{
			case 0:
				x = i - 1;
				y = j;
				break;
			case 1:
				x = i;
				y = j + 1;
				break;
			case 2:
				x = i + 1;
				y = j;
				break;
			case 3:
				x = i;
				y = j - 1;
				break;
			}

			if (mg[x][y] == 0)
			{
				e.x = x;
				e.y = y;
				e.pre = q->front;  //将可通方格的前一位置记为当前方格的存入队列中顺序
				EnQueue(q, e);
				mg[x][y] = 1;
			}	//将当前方格四个方向所有可通路存入队列中
		}
	}

	putchar('\n');
	cout << "Not Found";	//迷宫查找结束,未能找到终点
	delete q;
}

int main()
{
	int M, N, i, j;
	cin >> M >> N;	//输入迷宫的行,列

	for (i = 0; i < M + 2; i++)
	{
		mg[i][0] = 1;
		mg[i][M + 1] = 1;
	}
	for (i = 0; i < N + 2; i++)
	{
		mg[0][i] = 1;
		mg[M + 1][i] = 1;
	}
	for (i = 1; i < M + 1; i++)
	{
		for (j = 1; j < N + 1; j++)
		{
			cin >> mg[i][j];
		}
	}	//将迷宫初始化,在外围建立一堵墙

	SearchPath(1, 1, M, N);	//查找迷宫起点到终点是否有通路

	return 0;
}

运行结果如下:
关于用栈和队列分别解决走迷宫问题的方法讨论(参与者:陈卓,毛敏磊)

2.关于用栈解决:

对于迷宫问题用栈解决主要基于栈的特性Last in First Out(后进先出),可以很好的存储走迷宫时的中间状态——经过的路径。根据先进后出的特点可以大概想到看先将走过的路径存入栈内,当路走不通时将栈中的该路径弹出。同时根据迷宫的特点我们想到用二维数组来储存我们的迷宫。那么大概的思路便是遍历迷宫中的路径,将路径存入栈内,当所在路径没有新的路可走时开始回退也就是将栈内的元素弹出直到栈顶元素可以找到新的路径。
根据大概的思路先来定义会使用到的数据结构。

(1)对于迷宫中位置的存储定义一个数据结构,基于我们是用二维数组来存储迷宫,那么可以采用横坐标和纵坐标来描述位置。同时遍历路径我们需要一个能反映当前方向的变量所以有以下定义:

typedef struct
{
   int x, y;
   int di;//按照东南西北的顺序,di从1-4.
}Box;

(2)根据用横纵坐标来存储位置信息,可以使用横坐标和纵坐标的增减来表示移动因此可以定义一个结构数组来表示增减量所以有以下定义:

typedef struct
{
    int x, y;//用x,y的增量来表示移动
}Direction;
Direction direct[5]{ {0,0},{1,0},{0,-1},{-1,0},{0,1} };//设定按东南西北的顺序来寻找出口

现在开始正式思考如何寻找迷宫的出口。首先找迷宫有两大步骤:1)在没路时能将栈内的元素弹出。2)能遍历迷宫能走的位置。那么我们可以设置双层循环嵌套,将遍历迷宫位置的步骤作为内层循环,弹出栈内元素作为外层循环。当遍历迷宫位置无路可走时退出内层循环进入外层循环将元素弹出直到有新的路径出现时。
同时对于走过的路径也应进行标记使系统能识别该位置走过,那么我们采用将走过的路的值赋为-1(用1表示迷宫的墙,0来表示可走的路)。
以下是代码的具体实现(栈):

#include<iostream>
#include<stack>

using namespace std;

typedef struct
{
    int x, y;    //用x,y的增量来表示移动
}Direction;

typedef struct
{
    int x, y;
    int di;
}Box1;          //用来储存当前的位置和方向(栈)

int mg[1002][1002];		//定义一个存放迷宫的二维数组

int findPath(int M, int N);

int main()
{
    int M, N, i, j;
    cin >> M >> N;		

    for (i = 0; i < M + 2; i++)
    {
        mg[i][0] = 1;
        mg[i][M + 1] = 1;
    }
    for (i = 0; i < N + 2; i++)
    {
        mg[0][i] = 1;
        mg[M + 1][i] = 1;
    }
    for (i = 1; i < M + 1; i++)
    {
        for (j = 1; j < N + 1; j++)
        {
            cin >> mg[i][j];
        }
    }		//将迷宫初始化,在外围建立一堵墙

    findPath(M, N);

    return 0;
}

int findPath(int M, int N)
{
    Box1 temp;
    stack<Box1> s;
    int x, y, di;//存储当前地点的横坐标和纵坐标
    int x1, y1;//存储下一个地点的横坐标和纵坐标
    Direction direct[5]{ {0,0},{1,0},{0,-1},{-1,0},{0,1} };//设定按东南西北的顺序来寻找出口
    mg[1][1] = -1;//将记过的地方设置为-1
    temp = { 1,1,0 };
    s.push(temp);//为循环同一先将入口存入栈内
    while (!s.empty())
    {
        temp = s.top();
        s.pop();
        x = temp.x;
        y = temp.y;
        di = temp.di + 1;
        while (di <= 4)//方向未尝试完
        {
            x1 = x + direct[di].x;
            y1 = y + direct[di].y;
            if (mg[x1][y1] == 0)
            {
                temp = { x,y,di };
                s.push(temp);
                x = x1;//移动到下一个地点
                y = y1;
                mg[x1][y1] = -1;
                if (x == M && y == N)
                {
                    cout << '(' << M << ',' << N << ')' << endl;
                    while (!s.empty())
                    {
                        cout << '(' << s.top().x << ',' << s.top().y << ')' << endl;
                        s.pop();
                    }
                    return 1;
                }//迷宫有路
                else {
                    di = 1;
                }
            }
            else {
                di++;
            }

        }
    }
    cout << "Not Found!";//返回0说明迷宫没有路
    return 0;
}

运行结果如下
关于用栈和队列分别解决走迷宫问题的方法讨论(参与者:陈卓,毛敏磊)文章来源地址https://www.toymoban.com/news/detail-844291.html

总结:对于用栈和队列解决迷宫问题本质上是源于对栈和队列特点的利用,LIFO(后进先出)和FIFO(先进先出),基于此特点还可以解决更多同类问题如:查找文件指定名,对扑克牌排序和蜘蛛纸牌等,感兴趣的人也可去加以尝试,此后也将分享有关这方面的代码和知识,感谢阅览。

到了这里,关于关于用栈和队列分别解决走迷宫问题的方法讨论(参与者:陈卓,毛敏磊)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第10天-代码随想录刷题训练-第五章 栈和队列- ● 理论基础 ● 232.用栈实现队列 ● 225. 用队列实现栈

    栈和队列对应的三个不同的STL版本,底层实现方式不一样, 为我们所知道的是 SGI STL 栈 栈提供 pop和push等接口, 不提供走访功能 也不提供迭代器, 不像map和set可以使用迭代器遍历,往往不被归类为容器,而是容器适配器 栈的内部实现结构可以使用 verctor、list 和 deque(默认)

    2024年02月04日
    浏览(29)
  • 用栈求解迷宫问题的所有路径及最短路径程序(纯c语言)

    参考了这个博客 学校作业,在各种地方搜了半天,看别人的要么就是有点错,要么就是很复杂用了不少我不知道的库,还要么就是只求了一条路径,还要么就是用了c++没学过。 写了半天,写出了一个应该是比较简单的方法,应该是还能优化,不过作业能跑就行,懒得搞了。

    2023年04月12日
    浏览(25)
  • 数据结构上机实验——栈和队列的实现、栈和队列的应用、进制转换、约瑟夫环问题

      1.利用栈的基本操作实现将任意一个十进制整数转化为R进制整数。   2.利用循环队列实现.约瑟夫环问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到k的那个人出圈;他的下一个人又从1开始报数,数到k的那个人出圈;依

    2024年02月08日
    浏览(31)
  • 迷宫问题:BFS(队列,最短路径)和DFS(栈

    搜索的基本算法分为两种:宽度优先搜索(Breadth-First Search,BFS)以及深度优先搜索(Depth-First Search,DFS)。 在学习过程中我们常常会遇到许多需要用搜索解决的问题。比如迷宫。 这次专题主要是对栈和队列的应用进行分析。所以首先我们先简要描述一下DFS和BFS方便大家对下

    2024年02月09日
    浏览(27)
  • 数据结构--栈和队列--停车场问题

    目录 一、问题描述 二、实验目的 三、需求分析 四、方法描述 五、代码实现 六、实验结果测试 设停车场内只有一个可停放 n 辆汽车的狭长通道,且只有一个大门可供汽车进出,汽车在停车场内按车辆到达时间的先后顺序,依次由北向南排列(大门在最南端,最先到达的第一

    2024年02月22日
    浏览(32)
  • 关于在Vscode安装clangd的教程(分别在linux和windows)[很详细,很细节,很全!]【Windows端:缺少 language enginee的解决方法】

    一.背景: 在Vscode中,使用c/c++ 编译器(插件),但是自带的补全语法不好 clang 也是个编译器,而其对应的clangd的补全语法的功能很友善 所以在Vscode中,我们可以使用插件c/c++编译和执行,但是补全的语法用clangd,话不多说,直接开干! 安装分为2部分,linux端和本地端 1.先在

    2024年02月20日
    浏览(29)
  • 【用队列实现栈】【用栈实现队列】Leetcode 232 225

    ---------------🎈🎈题目链接 用队列实现栈🎈🎈------------------- ---------------🎈🎈题目链接 用栈实现队列🎈🎈-------------------

    2024年01月20日
    浏览(36)
  • leetcode 232.用栈实现队列

    🌟 leetcode链接:用栈实现队列 1️⃣ 思路和图解: push: pop: peek: 和 pop 类似。 代码: ✨ 栈和队列相关接口代码(可复制): 【数据结构】栈和队列

    2024年02月13日
    浏览(30)
  • 【数据结构】用栈实现队列

    前言:本节博客分享了用栈实现队列效果的思路以及代码,有需要借鉴即可。 LINK 如果要用栈实现队列,我们直到栈是先入后出的一个效果,所以我们可以用两个栈,这样逆转两次数不就是入栈之前数组的顺序嘛。下面是一些图辅助理解: 完。

    2024年03月10日
    浏览(46)
  • 数据结构-用栈实现队列

    前言: 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty): 实现 MyQueue 类: void push(int x) 将元素 x 推到队列的末尾 int pop() 从队列的开头移除并返回元素 int peek() 返回队列开头的元素 boolean empty() 如果队列为空,返回 true ;否

    2023年04月08日
    浏览(74)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包