class QueueUnderflow(ValueError):
"""队列为空"""
pass class SQueue:
def __init__(self, init_len=5):
self._len = init_len # 存储区长度
self._elems = [0] * init_len # 元素存储
self._head = 0 # 表头元素下标
self._num = 0 # 元素个数 def is_empty(self):
return self._num == 0 def peek(self):
"""查看队头元素"""
if self._num == 0:
raise QueueUnderflow
return self._elems[self._head] def dequeue(self):
"""出队"""
if self._num == 0:
raise QueueUnderflow
e = self._elems[self._head]
self._head = (self._head + 1) % self._len
self._num -= 1
return e def enqueue(self, e):
"""入队"""
if self._head == self._len - 1:
self._extend()
self._elems[(self._head + self._num) % self._len] = e
self._num += 1 def _extend(self):
"""扩容操作"""
old_len = self._len
self._len *= 2
new_elems = [0] * self._len
for i in range(old_len):
new_elems[i] = self._elems[(self._head + i) % old_len]
self._elems, self._head = new_elems, 0 def print(self):
"""打印从队头开始"""
end = self._head + self._num
print("list:", self._elems[self._head:end])

python的deque类:

import collections
# deque双端队列,支持元素的两端插入和删除,采用一种双链表技术实现
d = collections.deque()
d.append(1)
d.append(2)
d.appendleft(0)
print(d) # deque([0, 1, 2])

迷宫的递归求解:

def make(maze, pos):
"""标记maze为已走过"""
maze[pos[0]][pos[1]] = 2 def passable(maze, pos):
"""检查maze位置是否可行"""
return maze[pos[0]][pos[1]] == 0 def find_path(maze, pos, end):
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 东,南,西,北
make(maze, pos)
if pos == end:
print(pos, end=' ')
return True
for i in range(4):
nextp = [pos[0] + dirs[i][0], pos[1] + dirs[i][1]]
if passable(maze, nextp):
if find_path(maze, nextp, end):
print(pos, end=' ')
return True
return False def mazes():
"""初始化迷宫"""
map = []
for i in range(8):
map.append([])
for j in range(7):
if i == 0 or i == 7 or j == 0 or j == 6:
map[i].append(1)
else:
map[i].append(0)
return map def showMap(map):
"""打印迷宫"""
row, col = len(map), len(map[0])
for i in range(row):
for j in range(col):
print(map[i][j], end='\t')
print()
print() if __name__ == '__main__':
mmap1 = mazes()
showMap(mmap1)
print(find_path(mmap1, [1, 1], [6, 5]))
showMap(mmap1)
"""
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1 [6, 5] [5, 5] [4, 5] [3, 5] [2, 5] [1, 5] [1, 4] [1, 3] [1, 2] [1, 1] True
1 1 1 1 1 1 1
1 2 2 2 2 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 1 1 1 1 1 1
"""

基于栈的回溯解决迷宫问题:

def maze_solver(maze, start, end):
"""基于栈的回溯解决迷宫问题
算法框架:
入口start相关信息(位置和尚未探索方向)入栈;
while 栈不空:
弹出栈顶元素作为当前位置继续搜索
while 当前位置存在未走过的方向:
求出下一探测位置nextp
if nextp 是出口:
输出路径并结束
if nextp 未走过:
将当前位置和nextp顺序入栈并退出内层循环 """
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 东,南,西,北
if start == end:
print(start)
return
st = SStack()
make(maze, start) # 标记走过
# 4个方向分别编码为0,1,2,3,表示dirs的下标
st.push((start, 0)) # 入口和方向0入栈
while not st.is_empty():
pos, nxt = st.pop()
for i in range(nxt, 4):
nextp = [pos[0] + dirs[i][0], pos[1] + dirs[i][1]] # 算出下一位置
if nextp == end: # 到达出口
print(nextp, end=' ') # 终点位置
print(pos, end=' ') # 当前位置
st.print() # 经过的位置
return
if passable(maze, nextp): # 位置可行
st.push((pos, i + 1)) # 当前位置,与下一方向入栈,因为现在走的是i,如果回退就应走i+1了
make(maze, nextp)
st.push((nextp, 0)) # 新位置入栈,方向都是从0开始
break # 退出内层循环,下层讲以新栈顶为当前位置继续
print("no path found.") if __name__ == '__main__':
mmap1 = mazes()
showMap(mmap1)
print(maze_solver(mmap1, [1, 1], [6, 5])) """
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1 [6, 5] [5, 5] [([4, 5], 2), ([3, 5], 2), ([2, 5], 2), ([1, 5], 2), ([1, 4], 1), ([1, 3], 1), ([1, 2], 1), ([1, 1], 1)]
None
1 1 1 1 1 1 1
1 2 2 2 2 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 2 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1
"""

基于队列的迷宫求解算法:

def maze_solver_queue(maze, start, end):
"""基于队列的迷宫求解算法:
基本框架:
将start标记为已到达
start入队
while 队列里还有未充分探查的位置:
取出一个位置pos
检查pos的相邻位置
遇到end结束
未探查的都mark并入队
队列空,探索失败
"""
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)] # 东,南,西,北
if start == end:
print(start)
return
qu = SQueue()
make(maze, start)
qu.enqueue(start)
while not qu.is_empty():
pos = qu.dequeue()
for i in range(4):
nextp = [pos[0] + dirs[i][0], pos[1] + dirs[i][1]] # 算出下一位置
if passable(maze, nextp):
if nextp == end:
print("path find")
return
make(maze, nextp)
qu.enqueue(nextp)
print("No path.") if __name__ == '__main__':
mmap1 = mazes()
showMap(mmap1)
print(maze_solver_queue(mmap1, [1, 1], [6, 5]))
showMap(mmap1) """
1 1 1 1 1 1 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 0 0 0 0 0 1
1 1 1 1 1 1 1 path find
None
1 1 1 1 1 1 1
1 2 2 2 2 2 1
1 2 2 2 2 2 1
1 2 2 2 2 2 1
1 2 2 2 2 2 1
1 2 2 2 2 2 1
1 2 2 2 2 0 1
1 1 1 1 1 1 1
"""

从打印结果看,基于栈的搜索如果顺利,可能只探查不多的位置就找到出口,是一条路径;

基于队列的搜索是一种步步为营的搜索,只有在检查完所有与入口同样距离位置之后才更多前进一步

根据搜索过程的特点:把基于栈的搜索称为深度优先搜索,

基于队列的搜索称为宽度优先搜索

06.队列、python标准库中的双端队列、迷宫问题的更多相关文章

  1. STL标准库-容器-deque 双端队列

    头文件: #include<deque> 常用操作: https://www.cnblogs.com/LearningTheLoad/p/7450948.html

  2. (转)python标准库中socket模块详解

    python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...

  3. Python 标准库中的装饰器

    题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...

  4. 8、泛型程序设计与c++标准模板库2.3双端队列容器

    双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为& ...

  5. python中使用双端队列解决回文问题

    双端队列:英文名字:deque (全名double-ended queue)是一种具有队列和栈性质的抽象数据类型. 双端队列中的元素可以从两端弹出,插入和删除操作限定在队列的两边进行. 双端队列可以在 ...

  6. STL队列 之FIFO队列(queue)、优先队列(priority_queue)、双端队列(deque)

    1.FIFO队列   std::queue就是普通意思上的FIFO队列在STL中的模版. 1.1主要的方法有: (1)T front():访问队列的对头元素,并不删除对头元素 (2)T back(): ...

  7. C++实现python标准库中的Counter

    看python standard library by exmple里面提到一个Counter容器,它像muliset一样,能够维持一个集合,并在常量时间插入元素.查询某个元素的个数,而且还提供了一个 ...

  8. Python标准库中的生成器函数

    一.用于过滤的生成器函数 - 从输入的可迭代对象中产出元素的子集,而不修改元素本身 import itertools l1 = [1,2,3,4,5] l2 = [True,False,True,Fa ...

  9. python标准库中socket模块详解

    包含原理就是tcp的三次握手 http://www.lybbn.cn/data/datas.php?yw=71 这篇讲到了socket和django的联系 https://www.cnblogs.co ...

随机推荐

  1. 架构-数据库访问-SQL语言进行连接数据库服务器-OLE:OLE

    ylbtech-架构-数据库访问-SQL语言进行连接数据库服务器-OLE:OLE Object Linking and Embedding,对象连接与嵌入,简称OLE技术.OLE 不仅是桌面应用程序集 ...

  2. python json字符串中有int类型数字(不带引号)

    def jsonfy(s:str)->object: obj = eval(s, type('js', (dict,), dict(__getitem__=lambda s, n: n))()) ...

  3. GenericAPIView的使用及和视图扩展类的结合使用

    GenericAPIView的使用 from rest_framework.generics import GenericAPIView GenericAPIView继承 APIView,主要增加了操 ...

  4. python-笔记(二)数据类型

    一.数据类型是什么鬼? 计算机顾名思义就是可以做数学计算的机器,因此,计算机程序理所当然地可以处理各种数值.但是,计算机能处理的远不止数值,还可以处理文本.图形.音频.视频.网页等各种各样的数据,不同 ...

  5. memocached基础操作

    cmd->telnet方式链接(控制面板-启动该功能)telenet +ip +(端口号) memcahed 只有 string类型的 整个数据全部都是存在内存里面的 连接数 内存的大小 失效时 ...

  6. servlet过滤器Filter使用之DelegatingFilterProxy类

    正常情况下,我们需要添加一个过滤器,需要实现javax.servlet.Filter接口,再在web.xml中配置filter,如下: package cc.eabour.webapp.securit ...

  7. 【ABAP系列】SAP ABAP的事件执行顺序

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP的事件执行顺序 ...

  8. 好的计数思想-LightOj 1213 - Fantasy of a Summation

    https://www.cnblogs.com/zhengguiping--9876/p/6015019.html LightOj 1213 - Fantasy of a Summation(推公式 ...

  9. Web API 入门一

    之前我也了解过Web API 这部分,但是没有系统学习,更没有相关记录,故现在,写些博客记录入门学习过程.首先,关于API,只要学习编程的都应该知道,也都用过,API(应用程序编程接口)是一些预先定义 ...

  10. Codeforces 990C (模拟+组合数学)

    题面: 传送门 分析: 此题O(n2l)" role="presentation" style="position: relative;">O( ...