博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构之栈与队列
阅读量:6608 次
发布时间:2019-06-24

本文共 6587 字,大约阅读时间需要 21 分钟。

一 栈的简介

 

 

栈是一个数据集合,可以理解为只能在一段进行插入或删除操作的列表

栈的特点:后进先出
栈的概念:栈顶,栈底
栈的操作:

  • 进栈(压栈):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) == 0sta = 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.frontq = 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 dequequeue = 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 Queueq = 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+1dirs = [    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 Falsemaze_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 dequedef 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 Falsemaze_path_queue(1, 1, 8, 8)

 

转载于:https://www.cnblogs.com/harryblog/p/10722305.html

你可能感兴趣的文章
Android SQLite详解
查看>>
Spark技术在京东智能供应链预测的应用
查看>>
SparkR-Install
查看>>
Tagger: Deep Unsupervised Perceptual Grouping
查看>>
Intellij idea 项目目录设置 与包的显示创建
查看>>
HDU 1016:Prime Ring Problem
查看>>
Impala的安装(含使用CM安装 和 手动安装)(图文详解)
查看>>
论程序猿的社会地位
查看>>
Android 布局自适应屏幕
查看>>
ionic 进入二级目录以后隐藏底部导航栏(tabs)
查看>>
android: 在APP中显示高德地图SDK
查看>>
js11--js与C++、java异同
查看>>
Android下载网络图片并缓存
查看>>
自然语言交流系统 phxnet团队 创新实训 项目博客 (三)
查看>>
Unity游戏小地图生成
查看>>
【3】JVM-OutOfMemory异常重现
查看>>
【Netty】codec框架
查看>>
NHibernate 集合映射深入 (第五篇) <set>,<list>,<map>,<bag>
查看>>
禁止右键,禁止选中,禁止网页复制的Js代码
查看>>
jquery中选择器input:hidden和input[type=hidden]的区别
查看>>