python数据结构与算法学习笔记:使用深度优先搜索和广度优先搜索解决迷宫问题


前言

搜索是算法中很基础的东西,目前笔者将其分类为深度优先搜索、广度优先搜索、树搜索。
我们现在探究迷宫问题可以用到深度优先搜索和广度优先搜索解决,两种方法各有优缺
笔者也是学习清华博士的数据结构和算法来写的
清华博士数据结构与算法


一、深度优先搜索

1、栈

在使用深度优先时我们先了解一下栈
笔者将栈喻为盒子,放东西的时候要从下往上放拿的时候要从上
在这里插入图片描述
栈的实现:
(铁汁不懂类和对象可以跳过这段程序哦)

class Stack:                  # 类
	def __init__(self):       # (个人理解)初始化类里面的变量
		self.stack = []       # 定义一个列表
	def push(self,element):   # 进栈
		self.stack.append(element)
	def pop(self):			  # 出栈
		return self.stack.pop()
	def get_top(self):       # 栈顶元素
		if len(self.stack) > 0:
			return self.stack[-1]
		else:               # 栈空报错
			raise IndexError("Stack is empty")
	def is_empty:
		return len(self.stack) == 0

2.深度优先搜索实现迷宫

  • 思路:从一个节点出发,任意方向找下一个能走的点,一直走到死胡同,退回上一个节点再找出路
  • 回溯法:一条道上走不通回到上一个路口换条路走
  • 使用栈存储路径
  • 缺点:不是最短路径
  • 优点:内存占用小
    图片仅供参考参考一下

迷宫问题
给定一个迷宫maze任意出入口,0是路1是墙,请找到一条路打印出路的下标
代码:

maze = [
	[0,1,0,0,0,0,0,0,0,0],
	[0,0,1,0,0,0,1,0,1,0],
	[1,0,0,0,1,1,0,0,1,0],
	[1,1,1,0,0,0,0,0,0,0],
	[1,0,0,0,0,1,1,0,0,0],
	[1,1,1,0,0,1,1,1,0,0],
	[1,1,0,0,1,0,0,1,1,0],
    [1,1,0,0,0,0,0,0,1,1],
    [0,0,0,1,0,0,1,0,0,0],
    [1,1,1,1,0,1,1,1,1,0]
    ]
   # lambda后的if判断防止越界
dirs = [
		lambda x,y:(x+1,y) if x<len(maze)-1 else (x,y),
		lambda x,y:(x-1,y) if x>0 else (x,y),
		lambda x,y:(x,y+1) if y<len(maze)-1 else (x,y),
		lambda x,y:(x,y-1) if y>0 else (x,y)
]

def maze_path(x1,y1,x2,y2):
	stack = []                                       # 定义一个栈(列表)存储路径
	stack.append((x1,y1))                            # 入口导入
	# 因为当没有路时会退回,当所有路径都退出来时证明没路了(stack中没有值了)
	while len(stack) > 0:   
		curNode = stack[-1]                         # 定义变量读取当前位置(初始化为入口)
		if curNode[0] == x2 and curNode[1] == y2:   # 终点
			for i in stack:
				print(i)                            # 打印路径
			return True
		for i in dirs:                              # 在当前位置找下一个节点
			nextNode = i(curNode[0],curNode[1])     # 下一个要走的节点
			if maze[nextNode[0]][nextNode[1]] == 0: # 判断下一个节点能不能走
				stack.append(nextNode)              # 可以走加入路径中
				maze[nextNode[0]][nextNode[1]] = 2  # 在地图上标记走过
				break
		else:                                       # 四个方向没有可以走的路
			maze[nextNode[0]][nextNode[1]] = 2
			stack.pop()                             # 回溯
	else:
		print("没路啦")
		return False
maze_path(0,0,9,9)		
	

二、广度优先搜索

1.队列

队列的介绍文字康不懂来康视频
队列分为环形队列,双向队列,单向队列
单向队列就是从一头进去从另一头出来
在这里插入图片描述
双向队列就是两头都能进出
在这里插入图片描述
在这里我们主要用到双向队列环形队列就不赘述了请移步到视频学习

  • 双向队列内置函数(记不住可以用列表代替哦)
from collection import deque
q = deque([1,2,3],4)        # 队列的大小是4个元素
q.append(4)                 # 右边进队
q.pop()                     # 右边出队
q.appendleft()              # 左边进队
q.popleft()                 # 左边出队

2.广度优先搜索实现迷宫

  • 思路:从一个节点开始,寻找所有接下来能走的节点,不断寻找直到找到出口
  • 使用队列(列表)存储当前考虑的节点
  • 框框是队列
  • 优点:当找到最短路径时停止
  • 缺点:需要更多的内存
    在这里插入图片描述
from collections import deque
maze = [
	[0,1,0,0,0,0,0,0,0,0],
	[0,0,1,0,0,0,1,0,1,0],
	[1,0,0,0,1,1,0,0,1,0],
	[1,1,1,0,0,0,0,0,0,0],
	[1,0,0,0,0,1,1,0,0,0],
	[1,1,1,0,0,1,1,1,0,0],
	[1,1,0,0,1,0,0,1,1,0],
    [1,1,0,0,0,0,0,0,1,1],
    [0,0,0,1,0,0,1,0,0,0],
    [1,1,1,1,0,1,1,1,1,0]
]

dirs = [
       lambda x,y:(x+1,y) if x<len(maze)-1 else (x,y),
       lambda x,y:(x-1,y) if x>0 else (x,y),
       lambda x,y:(x,y-1) if y>0 else (x,y),
       lambda x,y:(x,y+1) if y<len(maze[x])-1 else (x,y)
       ]

def print_r(path):
       curNode = path[-1]
       realpath = []                           # 存储最短路径

       while curNode[2] != -1:
              realpath.append(curNode[0:2])
              curNode = path[curNode[2]]      # 通过curNode[2](第三个元素)找到这条路的上一个节点存在路径中
       realpath.append(curNode[0:2])          # 起点
       realpath.reverse()
       for i in realpath:
              print(i)
                     
def maze_path(x1,y1,x2,y2):
       queue = deque()
       queue.append((x1,y1,-1))                # 起点
       # path[(0,0,-1)]存储所有路径的节点,并存储该节点的上一个节点的下标
       path = []                               
       while len(queue) > 0:
			  # 将队列中队首的元素赋值到当前位置,并将坐标移除队列,再加如到所有路径中去
              curNode = queue.popleft()        
              path.append(curNode)
              print(queue)
              print(path)
              
              if curNode[0] == x2 and curNode[1] == y2:
                     print_r(path)
                     return True
              # 因为广度优先搜索不需要回溯,所以当路走不通时我们不用管他
              for i in dirs:
                     nextNode = i(curNode[0],curNode[1])
                     if maze[nextNode[0]][nextNode[1]] == 0:
                            queue.append((nextNode[0],nextNode[1],len(path)-1))
                            maze[nextNode[0]][nextNode[1]] = 2
                            

       else:
              print("没路啦")
              return False

maze_path(0,0,9,9)


三、 进一寸有进一寸的欢喜

迷宫问题还可以使用递归,非递归的方法解决。
笔者也是刚刚学习算法
有不妥请指出,有不懂的请留言

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值