栈和队列—Python实现基本操作

本文介绍了栈和队列两种基本数据结构,包括它们的定义、实现方式(顺序表和链表)以及常见应用。栈遵循后进先出(LIFO)原则,常用于括号匹配等问题;队列遵循先进先出(FIFO)原则,广泛应用于任务调度等场景。文章提供了Python实现示例,便于理解。
摘要由CSDN通过智能技术生成

目录

概述

应用

栈抽象数据类型

栈的顺序表实现

栈的链表实现

栈的应用

队列

栈抽象数据类型

队列的list实现

队列的链表实现


概述

        栈和队列都是保存数据元素的容器。这两种结构支持的元素访问操作包括存入、查看、元素弹出。栈和队列主要用于在计算过程中保存临时数据,这些数据是计算中发现或者产生的,在后面的计算中可能需要使用它们。

        栈和队列也是最简单的缓存结构,它们只支持数据项的存储和访问,不支持数据项之间的任何关系,因此栈和队列的实现结构只需要保证元素存入和取出的顺序,并不需要记录和保证新存入的元素和容器中已有元素之间的任何关系。

  • 栈是后进先出关系结构,简称LIFO(Last In First Out)结构
  • 队列时先进先出关系结构,简称FIFO(First In First Out)结构

应用

栈和队列是计算中使用最广泛的缓存结构:

  • 计算过程分为一些顺序进行的步骤
  • 计算中执行的某些步骤会不断产生一些后面可能需要的中间数据
  • 产生的数据中有些不能立即使用,但又需要在将来使用
  • 需要保存的数据的项数不能事先确定

栈(stack)是一种容器,可存入、访问、删除数据元素。栈的基本性质保证,在任何时刻可以访问、删除的元素都是在此之前最后存入的那个元素。

栈抽象数据类型

Stack:
    Stack(self)       # 创建空栈
    is_empty(self)    # 栈是否为空,True/False
    push(self, elem)  # 将元素elem加入栈
    pop(self)         # 删除栈最后压入的元素并将其返回
    top(self)         # 取得栈最后压入的元素,不删除

栈的顺序表实现

class StackUnderflow(ValueError):  # 栈下溢(空栈访问)
    pass

class SStack():
    """
    基于顺序表实现栈类,用list对象_elems存储栈中元素,所有栈操作映射到list操作
    """
    def __init__(self):
        self._elems = []
        
    def is_empty(self):
        return self._elems == []
    
    def top(self):
        if self._elems == []:
            raise StackUnderflow("in top")
        return self._elems[-1]
    
    def push(self, elem):
        self._elems.append(elem)
    
    def pop(self):
        if self._elems == []:
            raise StackUnderflow("in pop")
        return self._elems.pop()

栈的链表实现

class LNode:
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_

class LStack():
    """
    基于链表实现,用LNode作为结点
    """
    def __init__(self):
        self._top = None
        
    def is_empty(self):
        return self._top is None
    
    def top(self):
        if self._top is None:
            raise StackUnderflow("in top")
        return self._top.elem
    
    def push(self, elem):
        self._top = LNode(elem, self._top)
        
    def pop(self):
        if self._top is None:
            raise StackUnderflow("in pop")
        p = self._top
        self._top = p.next
        return p.elem

栈的应用

1、括号匹配问题

思路:

  • 顺序扫描被检查正文(一个字符串)里的一个个字符
  • 检查中跳过无关字符(所有非括号字符都与当前处理无关)
  • 遇到开括号时将其压入栈
  • 遇到闭括号时弹出当时的栈顶元素与之匹配
  • 如果匹配成功则继续,发现不匹配时检查以失败结束
def check_parens(text):
    """括号配对检查函数"""
    parens = "()[]{}"
    open_parens = "([{"
    opposite = {")": "(", "]": "[", "}": "{"}  # 配对关系
    
    def parentheses(text):
        """括号生成器,每次调用返回text里的下一个括号和位置"""
        i, text_len = 0, len(text)
        while True:
            while i < text_len and text[i] not in parens:
                i += 1
            if i >= text_len:
                return
            yield text[i], i
            i += 1
    st = SStack()
    for paren, i in parentheses(text):
        if paren in open_parens:
            st.push(paren)
        elif st.pop() != opposite[paren]:
            print("Not matching is found at", i, "for", paren)
            return False
        # else:  配对成功,什么也不做,继续
    print("All parentheses are correctly matched.")
    return True

队列

栈抽象数据类型

Queue:
    Queue(self)           # 创建空队列
    is_empty(self)        # 队列是否为空,True/False
    enqueue(self, elem)   # 将元素elem加入队列
    dequeue(self)         # 删除队列里最早进入的元素并将其返回
    peek(self)            # 查看队列里最早进入的元素,不删除

队列的list实现

class QueueUnderFlow(ValueError):
    pass

class SQueue():
    def __init__(self, init_len=8):
        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._num == self._len:
            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 + 1) % old_len]
        self._elems, self._head = new_elems, 0

队列的链表实现

        链表实现队列操作没有实质性技术困难。由于需要在链接表的两端操作,从一端插入元素,从另一端删除。最简单的单链表只支持首端高效操作,在另一端操作需要O(n)时间,不适合作为队列的实现基础。带尾端指针的单链表,它支持O(1)时间的尾端插入操作。

        有了尾指针,尾端加入元素是O(1)时间操作,可以用作队列的入队操作enqueue。首端访问和删除都是O(1)时间操作,分别看作队列的peek和dequeue。实现单链表的技术可以直接用于队列,只需要修改几个名字。

class LNode:
    def __init__(self, elem, next_=None):
        self.elem = elem
        self.next = next_

class QueueUnderFlow(ValueError):
    pass

class LQueue():
    def __init__(self):
        self._head = None
        self._rear = None
    
    def is_empty(self):
        return self._head is None

    def enqueue(self, elem):
        if self._head is None:
            self._head = LNode(elem, self._head)
            self._rear = self._head
        else:
            self._rear.next = LNode(elem)
            self._rear = self._rear.next
    
    def dequeue(self):
        if self._head is None:  # 无结点,引发异常
            raise StackUnderflow("in dequeue")
        e = self._head.elem
        self._head = self._head.next
        return e
    
    def peek(self):
        if self._head is None:  # 无结点,引发异常
            raise StackUnderflow("in peek")
        return self._head.elem

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~卷心菜~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值