迷宫——数据结构验金石?(会了迷宫,数据结构你也就通关了)

一 深度分析迷宫之递归栈+深度优先算法

(1)迷宫栈之思路

①迷宫有图吧,怎么建立个这样的图呢?五行五列,二维数组呀,所以动态开辟空间。你也要有表示坐标的点吧,用一个结构体就能实现。

②我们的目的是走出去,所以要有起点和终点吧所以要定义个起点作为探索迷宫的开始。至于终点就没有必要定义了。设置一个判断条件就能判断是否走到终点

③我们把‘’1‘’代表墙体走不通,‘’0‘’代表走的通。如果遇到0代表能走这就是一个判断条件

④整体上我们用递归来实现也就是深度优先算法。我们在进行探索迷宫时怎么探索呢?是不是要左右上下都要进行探索呀。所以要设置四个方向的探索代码。如果是0就返回true,继续探索,如果满足出口坐标就返回true直接找到出口。如果是1就返回false,从上一个再次探索,如果四个方向都没有找到出口就返回false没有找到出口。

⑤最后我们要打印代码,所以我们想到用栈来接受数据,用栈接受的数据出栈再打印会逆序打印。聪明的人类便想到再次定义一个栈,这样根据栈先进后出原理就正确打印了,比如我的这张图会打印)(0,0),(1,0),(2,0),(3,0),(4,0),(4,1),(4,2),(4,3),(4,4)。然而在读进栈后栈的顶层是(4,4),从栈顶读的话就变成逆序了(4,4),(4,3)……(0,0)。所以把栈里面的数据再次写到另外一个栈就变成栈顶是(0,0)读出去也就是(0,0),(1,0),(2,0),(3,0),(4,0),(4,1),(4,2),(4,3),(4,4)。具体代码实现下面会写到

(2)迷宫栈之代码

因为会牵扯到栈的代码这里我就不写栈带代码了。我的这篇文章有讲到过栈(C语言)栈和队列详解+实战解释-CSDN博客

先动态开辟数组,并定义起点

//动态开辟数组
int main
{
   int N=0,M=0;
   scanf("%d%d",&N,&M);
   int**maze=(int**)malloc(sizeof(int*)*N);//开创N行,这里maze是相当与数组名
   for(int i=0;i<M;++i)
   {
     maze[i]=(int*)malloc(sizeof(int)*M);  //开创M列,maze[i]指的是行
   }
   //定义起点坐标
    PT entry = { 0,0 };
 
  //判断是否找到出口

  if (GetMazePath(maze, N, M, entry))
  {
      printf("找到出口");
  }
  else
  {
      printf("没有找到出口");
  }
   //切记开创空间后要释放,而释放也要有释放顺序。
   //先释放指向二维数组的列的指针,再释放指向行的指针
   //如果先释放指向行的指针,行数据没了,如何找到列数据进行释放呢?
   for(int i=0;i<M;++i)
   {
      free(maze[i]);
      maze[i]=NULL;
   }   
   free(maze);
   maze==NULL;
}

上面代码中PT是什么呢?我们要建立一个位置坐标,这个位置坐标有行和列。

typedef struct postion
{
    int row;
    int col;
}PT;

上面的GetMazePath是什么呢?这个函数是用来上下左右探索迷宫的,探索成功放回true,输入找到出口,反之找不到出口。

bool GetMazePath(int**maze,int N,int M,PT cur)
{
   //判断是否走到出口
   if(cur.row==N-1&&cur.col==M-1)
   {
     return true;
   }
   PT next;
   //确定已经走过的路
   maze[cur.row][cur.col]=2;
   next=cur;
   //向上探索
   next.row-=1;
   if (Ispass(maze, N, M, next))
   {
    GetMazePath(maze, N, M, next);
    return true;
   }

   //下
   next.row += 1;
   if (Ispass(maze, N, M, next))
   {
      GetMazePath(maze, N, M, next);
      return true;
   }

  //左
  next.col -= 1;
  if (Ispass(maze, N, M, next))
  {
    GetMazePath(maze, N, M, next);
    return true;
  }

  //右
  next.col += 1;
  if (Ispass(maze, N, M, next))
  {
    GetMazePath(maze, N, M, next);
    return true;
  }
 //如果都不行返回false
  return false;
}
bool IsPass(int**maze,int N,int M,PT pos)
{
    if (pos.row > 0 && pos.row < N && pos.col>0 && pos.col < M && maze[pos.row][pos.col] == 0)
 {
     return true;
 }
 else
 {
     return false;
 }
}

讲一下在我写代码时的困惑,可能你也会有。为什么   //确定已经走路 maze[cur.row[cur.col]=2;其实不仅是可以用二来表示用3,5,/,*都可以,只要不是0就行。为什么呢?不加不可以吗?我理解代码时觉得不加不影响呀?说明你没有真正理解代码内涵。不加的话会出现什么情况呢?会出现死循环。重点是探索时是上下左右探索,听懂点赞!!没听懂??如果不加2在进行上下左右探索时万一上探索是已经走过的路是不是用要去走应经走过的路了呀!!听懂掌声或点赞!!

在思路栏目中我讲了要用到栈。就是每一次 GetMazePath时候都要进行入栈操作,这里我写一段关于吧栈写到另外一个栈的代码

void PrintPath()
{
    ST rpath;//新定义一个栈
    StackInit(&rpath);
    while (!StackEmpty(&path))
    {
        StackPush(&rpath, StackTop(&path));
        StackPop(&path);
    }
    while (!StackEmpty(&rpath))
    {
       PT top = StackTop(&rpath);
       printf("(%d,%d)\n", top.row, top.col);
       StackPop(&rpath);

    }
    StackEmpty(&rpath);
}

(3)深度优先算法实战

上面我们的代码是用递归来实现的,其实更准确的说是深度优先算法,深度优先算法就是和上面代码思路一样,从起点开始,探索迷宫,直到到达出口或目标节点。这个过程就是使用递归来遍历深度优先所用可能路径。那么深度优先算法在企业中有什么应用呢?

1.图像识别和处理

深度优先算法在图像识别和处理方面拥有较高的准确率和稳定性,可以应用于企业进行图像数据的识别和处理,如人脸识别、物体检测等。

2.自然语言处理

深度优先算法在自然语言处理中的应用较为广泛,可以用于企业中文本分类、情感分析、语音识别等方面,为企业提供更准确、高效的语言处理服务。

3.推荐系统

深度优先算法在推荐系统中的应用可以根据用户的历史行为和购买习惯,推荐相关产品和服务,为企业提高销售额和用户满意度。深度优先算法较好地解决了推荐系统的冷启动问题。

4.数据挖掘

深度优先算法在数据挖掘领域中的应用可以通过对数据进行深入挖掘,发现隐藏在数据中的规律和趋势,提供有助于企业决策的数据支持。深度优先算法可以帮助企业挖掘海量数据中的有效信息,提高决策的准确性和效率。

二 大体分析迷宫之最短路径+广度优先算法

(1)最短路径分析

深度优先算法是一直往前探索,再递归。然而求最短路径,则不需要递归,即没有返回值。当找到出口深度优先算法算结束了,而广度优先算法还没完,还需要再次找最短路径下的出口。这样我们会思考如何返回去去找呢?这就要在深度优先算法的基础上,把走过的路径再给恢复。恢复完的路径再去探索。把探索完了的再去与最小的进行对比,最小的则是最优解。然而在代码设计上不是用话就能说清楚的。他的精妙之处比比皆是。

(2)代码

代码是在深度优先算法代码基础上进行查改补缺的

主要差别在判断找到出口后,如何更换最短路径栈。和如何恢复已经走过的路径。

//在探索出口函数中进行相应的改动
if (cur.row == 0 && cur.col == M - 1)
	{
		// 找到了更短的路径,更新minpath;

		if (StackEmpty(&minpath)   
			|| StackSize(&path) < StackSize(&minpath))
		{
			StackDestory(&minpath);
			StackCopy(&path, &minpath);
		}
	}

StackCopy这个函数就是交换栈的。

void StackCopy(Stack* ppath, Stack* pcopy)
{
    //开创短路径大空间大小
	pcopy->a = (STDataType*)malloc(sizeof(STDataType*)*ppath->capacity);
    //把minpath 改成短路径下的数据
	memcpy(pcopy->a, ppath->a, sizeof(STDataType)*ppath->top);
	pcopy->top = ppath->top;
	pcopy->capacity = ppath->capacity;
}

需要注意的是在每一次上下左右都探索到出口后要进行恢复

	// 恢复一下
	maze[cur.row][cur.col] = 1;
	StackPop(&path);

(3)广度优先算法实战

迷宫求解: 在游戏开发中,BFS可以用于寻找从起点到终点的最短路径,帮助玩家在迷宫中导航。

社交网络分析: 企业可以利用BFS分析社交网络中的关系链,识别关键影响者或找到社区中的重要人物。

游戏AI: 在游戏开发中,BFS可以用于AI的路径规划,帮助游戏中的NPC(非玩家角色)找到移动到特定位置的最短路径。

地图导航: 在地图服务和导航系统中,BFS可以帮助用户找到从一个地点到另一个地点的最短路径。

网络安全 企业可以应用BFS算法来识别网络安全威胁,比如通过分析网络流量来检测潜在的恶意软件传播路径。

网络架构设计: 在设计企业网络架构时,BFS可以帮助确定网络中不同节点的最佳连接顺序,以优化数据传输效率。

供应链管理: 企业可以利用BFS来优化供应链网络,通过分析供应商和分销商的关系来找到最有效的物流路径。

故障检测与诊断: 在电信网络或企业内部网络中,BFS可以用来快速定位故障源头,从而加速故障恢复过程。

推荐系统: 在电子商务平台,BFS可以用于推荐系统中,通过分析用户行为和产品关系图来推荐相关产品。

负载均衡: 在云计算环境中,BFS可以帮助实现负载均衡,通过分析服务器之间的连接关系来分配任务。

三 深度优先和广度优先对比

深度优先算法(DFS)不像广度优先算法一样逐层搜索,而是沿着路径尽可能远地搜索图的深度,直到到达目标节点或遇到无法继续前进的节点。在搜索过程中,这种算法可能会陷入死循环或者找到一个深度较大但是并不是最佳解的路径。不过,它的执行效率很高,常用于解决迷宫问题和生成括号序列等场景。

广度优先算法(BFS)则是从起点开始,按照层级顺序逐层搜索,先去遍历离起点最近的节点,然后是次近的节点,以此类推。尽管搜索过程的效率比深度优先慢,但是广度优先通常会得到较优解,因为它能够保证找到最短路径。广度优先算法常用于解决最短路径和迷宫问题等。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值