二.python中的栈和队列

1.栈


特点:后进先出 LIFO (last in , first out)
概念:栈顶 栈底, 入栈出栈都是从栈顶
基本操作:
入栈push
出栈pop
取栈顶get_top
实现:
用列表实现

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952
"""
栈
特点:后进先出 LIFO (last in , first out)
概念:栈顶 栈底, 入栈出栈都是从栈顶
基本操作:
    入栈push
    出栈pop
    取栈顶gettop
实现:
    用列表实现
"""

"""
栈的简单实现
"""


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:
            return None

    def is_empty(self):
        return len(self.stack) == 0

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop())

"""
栈的使用:括号匹配问题
"""


def brace_match(s):
    match = {'}':'{', ']':'[', ')':'('}
    stack = Stack()
    for ch in s:
        if ch in ['(', '[', '{']:
            stack.push(ch)
        else:
            if stack.is_empty():
                return False
            elif stack.get_top() == match[ch]:
                stack.pop()
            else:
                return False

    return stack.is_empty()


print(brace_match('[{()}{{[()]}}]'))
print(brace_match('[{}()}{{[()]}}]'))

2.队列

队列
特点:先进先出 FIFO
概念:队尾(rear)入队, 队头(front)出队
基本操作:
入队
出队

环形队列的简单实现:
空队列: rear == front
入队: rear = (rear+1) % max_len
出队: front = (front+1) % max_len
队满: front == (rear + 1) % max_len
空出一个元素空间,以区分队空和队满,即front位置上始终为空,t长度5的队列只能放4个元素
循环: 对max_len取余

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952
"""
队列
特点:先进先出 FIFO
概念:队尾(rear)入队, 队头(front)出队
基本操作:
    入队
    出队
"""

"""
环形队列的简单实现:
    空队列: rear == front
    入队:   rear = (rear+1) % max_len
    出队:   front = (front+1) % max_len
    队满:   front == (rear + 1) % max_len
    空出一个元素空间,以区分队空和队满,即front位置上始终为空,t长度5的队列只能放4个元素
    循环:   对max_len取余
"""


class Queue:
    def __init__(self, size=100):
        self.queue = [0 for _ in range(size)]
        self.size = size
        self.rear = 0  # 队尾指针
        self.front = 0  # 队首指针

    def push(self, element):
        if not self.is_full():
            self.rear = (self.rear + 1) % self.size
            self.queue[self.rear] = element
        else:
            raise IndexError("Queue is full.")

    def pop(self):
        if not self.is_empty():
            self.front = (self.front + 1) % self.size
            return self.queue[self.front]
        else:
            raise IndexError("Queue is empty.")

    def is_empty(self):
        return self.rear == self.front

    def is_full(self):
        return (self.rear + 1) % self.size == self.front


q = Queue(5)
for i in range(4):
    q.push(i)
print(q.is_full())
print(q.pop())
q.push(5)

"""
python内置 双向列表deque:
两端都支持进队和出队操作
"""
from collections import deque
# q = deque([2,3,4], 5)  # 5是最大长度,队满后自动出队
# q.append(1)  # 队尾进队
# print(q.popleft())  # 队首出队
#
# q.appendleft(2)  # 队首进队
# q.pop()  # 队尾出队

#创建一个大小为5的队列,每读一行自动入队,5个后自动出队,最后剩余文件test.txt的最后5行
def tail(n):
    with open('test.txt', 'r') as f:
        q = deque(f,n)
        return q

for line in tail(5):
    print(line, end='')

3.迷宫问题的栈解决方法

问题描述:
给一个二维列表,表示迷宫(0表示通道,1表示围墙)
给出算法,求一条走出迷宫的路径

栈–深度优先搜索
回溯法
思路:
从一个节点开始,任意找下一个能走的点,
当找不到能走的点时,退回上一个点寻找是否有其他路径
使用栈存放整个路径
栈解决给出不一定是最短路径

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952
"""
给一个二维列表,表示迷宫(0表示通道,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):
    stack = []
    stack.append((x1, y1))
    while len(stack) > 0:
        curNode = stack[-1]
        if curNode == (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:
                stack.append(nextNode)
                maze[nextNode[0]][nextNode[1]] = 2  # 2 表示已经走过
                break
        else:
            maze[curNode[0]][curNode[1]] = 2
            stack.pop()
    else:
        print("没有通路")
        return False


maze_path(1,1,8,8)

4.迷宫问题的队列解决方法

队列–广度优先搜索
思路:
从一个节点开始,寻找所有接下来能走的点
继续不断寻找,直到找到出口
使用队列存储当前正在考虑的节点,如何输出路径?
找到终点后,倒着找回去,需要一个额外的列表记录出队的节点
队列解决给出的结果是最短路径

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# author: Xiang Hai
# wechat: xiaoyou42952
"""
队列--广度优先搜索
思路:
    从一个节点开始,寻找所有接下来能走的点
    继续不断寻找,直到找到出口
使用队列存储当前正在考虑的节点,如何输出路径?
    找到终点后,倒着找回去,需要一个额外的列表
"""
from collections import deque

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 print_r(path):
    curNode = path[-1]
    realpath = []
    while curNode[2] != -1:
        realpath.append(curNode[0:2])
        curNode = path[curNode[2]]
    realpath.append(curNode[0:2])
    realpath.reverse()
    for node in realpath:
        print(node)

def maze_path_queue(x1, y1, x2, y2):
    queue = deque()
    queue.append((x1,y1,-1))  # -1 是上一个节点在path中的位置
    path = []
    while len(queue) > 0:
        curNode = queue.popleft()
        path.append(curNode)  # 存放走过的节点
        if curNode[0] == x2 and curNode[1] == y2:
            print("找到通路:")
            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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值