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. vue 使用props 实现父组件向子组件传数据

    刚自学vue不久遇到很多问题,刚好用到的分组件,所以就用到传递数据 弄了好久终于搞定了,不多说直接上代码 父组件: <template> <headers :inputName=&q ...

  2. Django的media配置与富文本编辑器使用的实例

    效果预览 文章列表 添加文章 编辑文章|文章详情|删除文章 项目的基本文件 项目的Model from django.db import models # 导入富文本编辑器相关的模块 from cke ...

  3. springmvc 读写分离

    推荐第四种:https://github.com/shawntime/shawn-rwdb 4种不方的读写分离实现方法 http://blog.csdn.net/lixiucheng005/artic ...

  4. k8s创建资源

        一.创建方式分类: 命令 vs 配置文件 Kubernetes 支持两种方式创建资源:   1.用 kubectl 命令直接创建(适用于少数的pod创建) kubectl run httpd- ...

  5. MVC 源码系列之控制器执行(一)

    控制器的执行 之前说了Controller的激活,现在看一个激活Controller之后控制器内部的主要实现. public interface IController { void Execute( ...

  6. 16/7/7_PHP-构造\解析函数

    昨天又问老师问题,老师还是强调要用博客之类记录下每天的学习的习惯. 我个人的想法是一些知识点不用笔记一下 在脑海的理解不是太深.但是老师都这么说了我老师乖乖的记录下今天的学习的一些知识.心得.技巧等等 ...

  7. 【ABAP系列】SAP 业务界面同时显示KEY和文本

      公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 业务界面同时显示KEY和 ...

  8. TensorFlow学习笔记7-深度前馈网络(多层感知机)

    深度前馈网络(前馈神经网络,多层感知机) 神经网络基本概念 前馈神经网络在模型输出和模型本身之间没有反馈连接;前馈神经网络包含反馈连接时,称为循环神经网络. 前馈神经网络用有向无环图表示. 设三个函数 ...

  9. oracle--表分区、分区索引

    --|/ range分区 create table sale( product_id varchar2(5), sale_count number(10,2) ) partition by range ...

  10. idea 社区版本创建javaweb项目 使用jetty

    idea社区版本 创建javaweb项目后使用jetty启动 <dependencies> <dependency> <groupId>javax.servlet& ...