zoukankan      html  css  js  c++  java
  • 数据结构之栈与队列

    一 栈的简介

    栈是一个数据集合,可以理解为只能在一段进行插入或删除操作的列表
    栈的特点:后进先出
    栈的概念:栈顶,栈底
    栈的操作:

    • 进栈(压栈):push
    • 出栈:pop
    • 取栈顶:gettop

    使用一般的列表结构可实现栈

    • 进栈: li.append
    • 出栈: li.pop
    • 取栈顶: li[-1]

    Python代码实现栈:

    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
    
    sta = stack()
    sta.stack = [1, 2]
    sta.push(5)
    print(sta.pop())
    print(sta.pop())
    print(sta.pop())
    print(sta.is_empty())

     二 栈的应用示例 —— 括号匹配问题

    括号匹配问题: 给一个字符串,其中包括小括号,中括号,大括号,求该字符串中的括号是否匹配
    例如:

    • ()()[]{} 匹配
    • ([{()}]) 匹配
    • []( 不匹配
    • [(]) 不匹配
    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:  # stack.get_top() != match[ch]
                    return False
    
        return '匹配成功'
    
    
    print(brace_match(["{", "(", ")", "}"]))

    三 队列的简介

    • 队列是一个数据集合,仅允许在列表的一端进行插入,另一端进行删除,
    • 进行插入的一端称为队尾(rear),插入动作称之为进队或入队
    • 进行删除的一端称之为对头(front),删除动作称为出队
    • 队列的性质:先进先出

    双向队列:对列的两端都允许进行进队和出队操作

    队列的实现

    队列能否简单用列表实现?为什么?

    • 初步设想:列表+两个下标指针
    • 创建一个列表和两个变量,front变量指向队首,rear变量指向队尾。初始时,front和rear都为0。
    • 进队操作:元素写到li[rear]的位置,rear自增1。
    • 出队操作:返回li[front]的元素,front自减1。

    队列的实现原理-----环形对列

     

    环形队列:当队尾指针front == Maxsize + 1时,再前进一个位置就自动到0。

    • 实现方式:求余数运算
    • 队首指针前进1:front = (front + 1) % MaxSize
    • 队尾指针前进1:rear = (rear + 1) % MaxSize
    • 队空条件:rear == front

    队列实现代码

    class Queue:
        def __init__(self, size=100):
            self.queue = [0 for _ in range(size)]
            self.rear = 0  # 队尾指针
            self.front = 0  # 队首指针
            self.size = size
    
        def push(self, element):
            if not self.is_filled():
                self.rear = (self.rear + 1) % self.size
                self.queue[self.rear] = element
            else:
                raise IndexError('Queue is filled')
    
        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_filled(self):
            return (self.rear+1) % self.size == self.front
    
    q = Queue(5)
    for i in range(4):
        q.push(i)
    
    print(q.is_filled())
    print(q.pop())
    q.push(5)
    print(q.pop())
    print(q.pop())
    print(q.pop())
    print(q.pop())

    对列的内置模块

    from collections import deque
    queue = deque()#创建队列
    queue.append('first')
    queue.append('second')
    queue.append('third')
    print(queue.popleft())
    print(queue.popleft())
    print(queue.popleft())#出队,,先进先出
    print([i for i in queue])  #查看队列里的元素
    
    queue.appendleft('one')#双向队列队首进队
    queue.appendleft('two')#双向队列队首进队
    queue.appendleft('five')#双向队列队首进队
    print(queue.pop())
    print(queue.pop())#双向队列从队尾出队
    print([i for i in queue])
    
    
    
    #单向队列
    from queue import Queue
    q = Queue()
    q.put('a')
    q.put('b')
    q.put('c')
    print(q.get())  #a

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

    给一个二维列表, 表示迷宫(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]
    ]

    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]
    ]
    
    # 四个方向坐标 上x-1,y; 下x+1,y;  左:x, y-1; 右 x,y+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[0] == x2 and curNode[1] == y2:
                # 走到终点了:
                for p in stack:
                    print(p)
                return True
            # 四个方向坐标 上x-1,y; 下x+1,y;  左:x, y-1; 右 x,y+1
            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[nextNode[0]][nextNode[1]] = 2
                stack.pop()
        else:
            print('没有出路')
            return False
    
    
    maze_path(1, 1, 8, 8)

     2  队列实现广度搜索

    思路:

    • 从一个节点开始,寻找所有接下来能继续走的点,继续不断寻找,直到找到出口
    • 使用队列存储当前正在考虑的节点

    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)
    ]
    
    from collections import deque
    
    
    def print_r(path):
        real_path = []     # 出去的路径
        i = len(path) - 1  # 最后一个节点
        print(path)
        print(i)
        while i >= 0:      # 判断最后一个节点的标记是否为-1,如果是-1说明是起始点,如果不是-1就继续查找
            real_path.append(path[i][0:2])   # 拿到并添加节点x,y坐标信息
            i = path[i][2]                   # 这里i[2]是当前节点的前一步节点的标识:path的下标,因此path[i[2]]拿到前一节点
        real_path.reverse()                  # 将列表倒序,将前面生成的从后往前的列表变为从前往后
        for node in real_path:
            print(node)
    
    
    def maze_path_queue(x1, y1, x2, y2):
        queue = deque()
        path = []
        queue.append((x1, y1, -1))
        while len(queue) > 0:  # 当队列不空时循环
            cur_node = queue.popleft()  # 当前节点
            path.append(cur_node)
            if cur_node[0] == x2 and cur_node[1] == y2:
                # 到达终点
                print_r(path)
                return True
            for dir in dirs:
                next_node = dir(cur_node[0], cur_node[1])  # curNode[0],curNode[1]分别是当前节点x、y
                if maze[next_node[0]][next_node[1]] == 0:  # 如果有路可走
                    queue.append((next_node[0], next_node[1], len(path) - 1))  # 后续节点进队,标记谁让它来的:path最后一个元素的下标
                    maze[next_node[0]][next_node[1]] = 2  # 设置为2,标记为已经走过
    
        return False
    
    
    maze_path_queue(1, 1, 8, 8)
  • 相关阅读:
    zookeeper使用场景
    zookeeper安装配置
    hadoop 远程调试
    deep learning笔记
    Sentiment Analysis(1)-Dependency Tree-based Sentiment Classification using CRFs with Hidden Variables
    PRML阅读笔记 introduction
    Python 学习笔记(2)
    python nltk 学习笔记(5) Learning to Classify Text
    python nltk 学习笔记(4) Writing Structured Programs
    python nltk 学习笔记(3) processing raw text
  • 原文地址:https://www.cnblogs.com/harryblog/p/10722305.html
Copyright © 2011-2022 走看看