算法篇06---python队列的内置模块及其应用、栈和队列的应用

一、双向队列

两端都支持 进队 和 出队 操作。

双向队列的基本操作:

  • 队首进队、队首出队、队尾进队、队尾出队

二、python队列的内置模块

使用方法: from collections import deque

  • 创建队列: queue = deque()
  • 队尾进队: append( )   
  • 队头出队: popleft( )
  • 双向队列队首进队:qppendleft( )
  • 双向队列队尾出队: pop( )
from collections import deque
q = deque([1,2,3])

# 单向队列实现
q.append(4)      # 右边-队尾进队
print(q)             # deque([1,2,3,4])
print(q.popleft())   # 左边-队首出队  : 只要没有left,就都是右边队尾的操作

# 用于双向队列
 q.appendleft(0)   # 左边-队首进队
 q.pop()    # 右边-队尾出队

q2 = deque([1,2,3,4,5],5)  # 后边的参数是队列中数据个数,队满之后在加数据,前面的自动出队
q2.append(6)
print(q2)                    # deque([2,3,4,5,6])
print(q2.popleft())    # 2 出队

 队列的应用:打印文件后几行

                       前几行只需要for循环读,读到第五行break即可。

from collections import deque
def tail(n):
    with open('test.txt','r') as f:
        q = deque(f,n)   #创建一个容量为n的队列
        return q

print(tail(5))  # 打印出文件中的后5行,为什么会存后5行:
# 读f文件,从上到下,先将前n行存入队列; 接着再往后读,因为队列已满,前面的
# 只能出队,最后只剩下最后n行
for line in tail(5):   # 从队头开始出队
    print(line,end='')

>>>deque(['6\n', '7\n', '8\n', '9\n', '10'], maxlen=5)
>>>6
>>>7
>>>8
>>>9
>>>10

三、栈和队列的应用---迷宫问题

1. 栈——深度优先搜索:回溯法

        “一条路走到黑”

        思路:从一个节点开始,任意找下一个能走的点。当找不到能走的点时,退回上一个寻找是否有其他方向的点。

        使用栈存储当前路径(后进先出)

#深度优先搜索————栈————回溯法
maze = [
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]

# 决定查找的四个方向的先后
dirs = [
    lambda x, y: (x - 1, y),  # 上
    lambda x, y: (x + 1, y),  # 下
    lambda x, y: (x, y - 1),  # 左
    lambda x, y: (x, y + 1)  # 右
]

def maze_path(x1,y1,x2,y2):    # 起点(x1,y1)  终点(x2,y2)
    stack=[]  # 建栈
    stack.append((x1,y1))
    maze[x1][y1] = 2  # 将起点先标记为走过的路
    while len(stack) > 0:   # 栈不为空,继续循环
        curNode = stack[-1]  # 现在的位置

        if (curNode[0],curNode[1]) == (x2,y2):   # 如果找到终点:
            print('找到路了,路线如下:')
            for p in stack:
                print(p)
            return True

        for dir in dirs:
            nextNode = dir(curNode[0],curNode[1])
            if maze[nextNode[0]][nextNode[1]] == 0:   # 如果下一个位置为0 ,可以进栈
                stack.append(nextNode)
                maze[nextNode[0]][nextNode[1]] = 2   # 走过的位置 设为2
                break   # 某个方向上可以走,就进栈,进栈后就结束for,不在看其他方向

        else:            # 如果每个方向上都不为0:即没有路可走----退一步(出栈)
            stack.pop()

    else:         # 如果len(stack) == 0,空栈,说明没有路
        print('没有路')
        return False

maze_path(1,1,8,8)

1. 队列——广度优先搜索

同时考虑多条路!可以找到最短的那条

思路:从一个节点开始,寻找所有接下来能继续走的点,继续不断寻找,直到找到出口。

使用队列存储当前正在考虑的节点(已经考虑过的节点不在队列里存储)

 

maze = [
    [1,1,1,1,1,1,1,1,1,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,1,0,0,0,1,0,1],
    [1,0,0,0,0,1,1,0,0,1],
    [1,0,1,1,1,0,0,0,0,1],
    [1,0,0,0,1,0,0,0,0,1],
    [1,0,1,0,0,0,1,0,0,1],
    [1,0,1,1,1,0,1,1,0,1],
    [1,1,0,0,0,0,0,0,0,1],
    [1,1,1,1,1,1,1,1,1,1]
]
from collections import deque

# 决定查找的四个方向的先后
dirs = [
    lambda x, y: (x - 1, y),  # 上
    lambda x, y: (x + 1, y),  # 下
    lambda x, y: (x, y - 1),  # 左
    lambda x, y: (x, y + 1)  # 右
]

def print_r(path):
    curNode=path[-1]    
    real_path = []   # path不是真正的路径,是所有被出队的元素及其来源

    while curNode[2] != -1:   # 表示没到开头---继续往前找
        real_path.append(curNode[0:2])
        curNode = path[curNode[2]]

    real_path.append(curNode[0:2])       # 等到curNode[2]==1 时,说明到起点位置,也需要添加到真实路径
    real_path.reverse()
    for node in real_path:
        print(node)

def maze_path_queue(x1,y1,x2,y2):    # 起点(x1,y1)  终点(x2,y2)
    queue=deque()     # 创建一个队列:存储正在考虑的节点
    queue.append((x1,y1,-1))    # 起点(x1,y1),第三个参数代表来自哪个位置
    path=[]    # 每个元素里都是三维的
    while len(queue) > 0:    # 队列不为空,可以继续找
        curNode = queue.pop()  # 从该节点后面开始找
        path.append(curNode)    # 记录所有出队的数据,他代表下一个节点的来源
        if curNode[0] == x2 and curNode[1] == y2:   # 如果找到终点
            print_r(path)
            return True
        for dir in dirs:
            nextNode = dir(curNode[0],curNode[1])
            if maze[nextNode[0]][nextNode[1]] == 0:
                queue.append((nextNode[0],nextNode[1],len(path)-1))    # 第三个参数代标该节点的来源,它来源于已经出队的数据的位置——path
                maze[nextNode[0]][nextNode[1]] = 2
    else:
        print('没路了')
        return False

maze_path_queue(1,1,8,8)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值