06.队列、python标准库中的双端队列、迷宫问题
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标准库中的双端队列、迷宫问题的更多相关文章
- STL标准库-容器-deque 双端队列
头文件: #include<deque> 常用操作: https://www.cnblogs.com/LearningTheLoad/p/7450948.html
- (转)python标准库中socket模块详解
python标准库中socket模块详解 socket模块简介 原文:http://www.lybbn.cn/data/datas.php?yw=71 网络上的两个程序通过一个双向的通信连接实现数据的 ...
- Python 标准库中的装饰器
题目描述 1.简单举例 Python 标准库中的装饰器 2.说说你用过的 Python 标准库中的装饰器 1. 首先,我们比较熟悉,也是比较常用的 Python 标准库提供的装饰器有:property ...
- 8、泛型程序设计与c++标准模板库2.3双端队列容器
双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为& ...
- python中使用双端队列解决回文问题
双端队列:英文名字:deque (全名double-ended queue)是一种具有队列和栈性质的抽象数据类型. 双端队列中的元素可以从两端弹出,插入和删除操作限定在队列的两边进行. 双端队列可以在 ...
- STL队列 之FIFO队列(queue)、优先队列(priority_queue)、双端队列(deque)
1.FIFO队列 std::queue就是普通意思上的FIFO队列在STL中的模版. 1.1主要的方法有: (1)T front():访问队列的对头元素,并不删除对头元素 (2)T back(): ...
- C++实现python标准库中的Counter
看python standard library by exmple里面提到一个Counter容器,它像muliset一样,能够维持一个集合,并在常量时间插入元素.查询某个元素的个数,而且还提供了一个 ...
- Python标准库中的生成器函数
一.用于过滤的生成器函数 - 从输入的可迭代对象中产出元素的子集,而不修改元素本身 import itertools l1 = [1,2,3,4,5] l2 = [True,False,True,Fa ...
- python标准库中socket模块详解
包含原理就是tcp的三次握手 http://www.lybbn.cn/data/datas.php?yw=71 这篇讲到了socket和django的联系 https://www.cnblogs.co ...
随机推荐
- Java 实现 对象和转字符串之间的互转 (json格式)
添加依赖: <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId> ...
- Java基础数据类型小结
1. 记忆中的数据类型: 记忆中java一共有八种基础数据:boolean,byte,char,int,long,float,double,还有一种记不起来. 他们的长度分别为: 他们的用处 ...
- COUNT(*) vs COUNT(col)
w https://www.percona.com/blog/2007/04/10/count-vs-countcol/
- oracle alter index rebuild offline与online
oracle index build online与offline测试环境为oracle 11.2.0.4 --sql test SQL> conn test/test )); begin .. ...
- linux查找所有文件中某个字符串
查找目录下的所有文件中是否含有某个字符串 find .|xargs grep -ri "IBM" 查找目录下的所有文件中是否含有某个字符串,并且只打印出文件名 find .|xar ...
- 【MM系列】SAP MM中的委外加工与信息记录
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP MM中的委外加工与信息记录 ...
- 前端表格选中列合计,select-chosen,set集合,display隐藏
业务涉及到table选中列合计,同时隐藏未选中列.为了减少后端请求数据,前端获得所有数据后筛选计算. 1.select下拉框初始化 $(function() { $('.chosen-select') ...
- C程序优化
1 优化内存使用 后期程序优化的时候看内存分配是否浪费:是否留有安全裕量:有些内存是否分配过多,有些内存是否分配了没使用:尤其是创建对象的时候
- Acwing.835. Trie字符串统计(模板)
维护一个字符串集合,支持两种操作: “I x”向集合中插入一个字符串x: “Q x”询问一个字符串在集合中出现了多少次. 共有N个操作,输入的字符串总长度不超过 105105,字符串仅包含小写英文字母 ...
- CVE-2016-0822-MTK-drivers/misc/mediatek/connectivity/common/combo/linux/wmt_dev.c#1158
CVE-2016-0822-MTK-drivers/misc/mediatek/connectivity/common/combo/linux/wmt_dev.c#1158 //mediatek/ke ...