用python实现栈和队列并解释原理

大家好呀,又见面了,本次更新栈和队列,有不懂的小伙伴可以驻足学习,本文有错误之处请指出,不胜感激!
下面进入正文:

详情见数据结构的总思路设计图了解此处属于哪部分内容

线性表和栈都是常见的数据结构,在计算机科学中应用广泛。下面是线性表栈的知识点:

线性表是一种数据结构,可以用数组或链表实现。它是由一组元素组成的有序序列,这些元素按照线性顺序排列。

线性表支持的基本操作包括插入、删除和查找等,其中查找操作可以按照元素的位置或者值进行。

栈是一种特殊的线性表,它的插入和删除操作只能在栈顶进行。栈的特性是先进后出(LIFO),最后进入的元素先被删除。

栈有两种实现方式,一种是基于数组的实现,称为顺序栈;另一种是基于链表的实现,称为链式栈。

栈的基本操作包括入栈和出栈,其中入栈操作是将一个元素压入栈顶,出栈操作是将栈顶元素弹出。

栈还有一个常用的操作是查看栈顶元素,即返回栈顶元素但不弹出。

栈的应用场景非常广泛,比如表达式求值、括号匹配、函数调用栈等。

栈(Stack)是一种线性数据结构,它的特点是“先进后出”,即最后一个进入栈的元素,会成为第一个弹出栈的元素。栈是一种限定插入和删除操作的线性表,插入和删除操作只能在栈顶进行。
栈通常用于进行表达式求值、递归算法等领域。在计算机系统中,栈被广泛应用,比如程序的调用栈,操作系统中的进程栈等等。
栈有两种基本操作:入栈和出栈。入栈就是向栈顶位置插入一个元素,出栈就是从栈顶位置弹出一个元素。栈还有一个很重要的性质是空间效率高,因为它不需要像链表一样保存额外的指针来表示节点间的关系,只需要一个指向栈顶元素的指针即可。
栈的实现方式有多种,最常见的是使用数组或链表来实现。使用数组实现的栈叫做顺序栈,使用链表实现的栈叫做链式栈。在实际应用中,需要根据具体情况来选择不同的实现方式。

顺序栈

顺序表和链式表都是数据结构中的线性表,用来存储一组相同类型的数据元素,具有前驱后继关系。它们的主要区别在于存储方式的不同。
顺序表是用一段连续的物理存储单元来存储线性表的,也就是说,它的数据元素在内存中是顺序存储的。顺序表可以随机访问,即通过元素的下标来访问,因此访问速度非常快。但是在插入和删除元素时,需要移动大量的数据,因此时间复杂度较高。

以下来用python实现顺序栈:

class SqStack(object):
    def __init__(self, maxsize=None):
        self.maxsize = maxsize
        self.stack = []    # 存储栈元素的列表,初始化为空列表
        self.top = -1      # 栈顶指针初始化为-1

    def __len__(self):
        return len(self.stack)

    def is_empty(self):
        return self.top == -1

    def is_full(self):
        return len(self.stack) == self.maxsize

    def push(self, value):
        if self.is_full():
            raise Exception('Stack is full')
        else:
            self.stack.append(value)  # 将新元素压入栈顶
            self.top += 1             # 栈顶指针加1

    def pop(self):
        if self.is_empty():
            raise Exception('Stack is empty')
        else:
            self.top -= 1             # 栈顶指针减1
            return self.stack.pop()  # 弹出栈顶元素

    def peek(self):
        if self.is_empty():
            return None
        else:
            return self.stack[self.top]  # 返回栈顶元素

链式栈

链式表是通过一些结点来存储线性表的,每个结点包含一个数据元素和一个指向下一个结点的指针。由于链式表的结点不一定是连续的,因此不支持随机访问,必须从表头开始遍历整个链表才能找到目标结点。在插入和删除元素时,只需要改变指针的指向,因此时间复杂度较低。

实现:

class Node(object):
    def __init__(self, value=None, next=None):
        self.value = value
        self.next = next

class LinkedStack(object):
    def __init__(self):
        self.top = None

    def is_empty(self):
        return self.top is None

    def push(self, value):
        self.top = Node(value=value, next=self.top)  # 将新元素作为新的栈顶

    def pop(self):
        if self.is_empty():
            raise Exception('Stack is empty')
        else:
            value = self.top.value    # 取出栈顶元素的值
            self.top = self.top.next  # 栈顶指针下移一位
            return value              # 返回栈顶元素的值

    def peek(self):
        if self.is_empty():
            return None
        else:
            return self.top.value     # 返回栈顶元素的值

在实际应用中,顺序表和链式表的选择取决于具体的场景和需求。如果需要随机访问元素的时间尽可能短,那么顺序表是一个不错的选择;如果需要经常插入和删除元素,那么链式表更加适合。当然,有些情况下需要综合考虑,比如需要支持高效的随机访问同时又需要频繁的插入和删除操作,这时可以采用其他的数据结构,如平衡树等。

队列(Queue)

队列(Queue)是一种线性数据结构,具有先进先出(First In First Out,FIFO)的特点。与栈不同的是,队列只允许在队尾插入元素,在队头删除元素。
在队列中,我们通常称添加元素的操作为入队(enqueue),删除元素的操作为出队(dequeue)。同时,队列还有一个重要的概念——队头(front)和队尾(rear)。
队头是指队列中的第一个元素,也就是将要被删除的元素;队尾是指队列中的最后一个元素,也就是将要被添加的元素。
队列通常有两种实现方式,一种是顺序队列,一种是链式队列。
顺序队列的底层实现是一个数组,数组中的每一个元素代表队列中的一个元素,队列头指针 front 和队列尾指针 rear 分别指向队头和队尾元素的下标。顺序队列的特点是随机访问快,但插入和删除的时间复杂度较高。
链式队列的底层实现是一个链表,队列头指针 front 和队列尾指针 rear 分别指向链表的头和尾节点。链式队列的特点是插入和删除的时间复杂度较低,但随机访问较慢。
队列常见的应用场景包括任务调度、消息传递、缓存等。
除了上述的应用场景,队列还可以用于:

多线程编程中的线程安全队列。比如Python中的queue模块提供了队列的线程安全实现,可以用于多线程编程中的任务分发、任务汇总等场景。

数据结构中的广度优先搜索。在图的遍历过程中,广度优先搜索可以使用队列实现,从而实现对图的层次遍历。

模拟等待队列。比如在操作系统中,当多个进程或线程同时需要访问共享资源时,可以使用队列来实现等待队列,从而保证资源的公平分配。

事件处理器。在事件驱动编程中,事件处理器可以使用队列实现。当事件触发时,将事件添加到队列中,由事件处理器依次处理队列中的事件。

总之,队列是一种非常常用的数据结构,在计算机程序设计和算法实现中都具有广泛的应用场景。

普通队列(Queue)

普通队列是一种先进先出(FIFO)的数据结构,可以通过数组或链表来实现。在队列中,数据只能从队尾进入队列,从队头出队。队列通常用于任务调度、消息传递、缓存等场景。
下面是一个使用 Python 实现的普通队列的代码,其中包括一些注释和解释:

class Queue:
    def __init__(self):
        self.items = []

    def is_empty(self):
        """检查队列是否为空"""
        return self.items == []

    def enqueue(self, item):
        """将元素添加到队列尾部"""
        self.items.append(item)

    def dequeue(self):
        """从队列头部移除元素并返回"""
        return self.items.pop(0)

    def size(self):
        """返回队列中元素个数"""
        return len(self.items)

双端队列(Deque)

双端队列是一种允许从队列两端添加或移除元素的数据结构。双端队列通常通过数组或链表来实现,可以在队列的两端添加和删除元素。
下面是一个使用 Python 实现的双端队列的代码,其中包括一些注释和解释:

class Deque:
    def __init__(self):
        self.items = []

    def is_empty(self):
        """检查队列是否为空"""
        return self.items == []

    def add_front(self, item):
        """将元素添加到队列前面"""
        self.items.insert(0, item)

    def add_rear(self, item):
        """将元素添加到队列尾部"""
        self.items.append(item)

    def remove_front(self):
        """从队列头部移除元素并返回"""
        return self.items.pop(0)

    def remove_rear(self):
        """从队列尾部移除元素并返回"""
        return self.items.pop()

    def size(self):
        """返回队列中元素个数"""
        return len(self.items)

阻塞队列(BlockingQueue)

阻塞队列是一种允许多个线程同时操作的队列。在阻塞队列中,如果队列为空,则获取元素的线程会被阻塞,直到队列中有新的元素。如果队列已满,则添加元素的线程会被阻塞,直到队列中有空闲位置。
下面是一个使用 Python 实现的阻塞队列的代码,其中包括一些注释和解释:

class BlockingQueue:
    def __init__(self, maxsize=0):
        self.queue = Queue(maxsize)  # 初始化一个Queue队列对象

    def put(self, item):
        """将元素添加到队列尾部,如果队列已满则阻塞"""

        self.queue.put(item)  # 调用Queue对象的put方法将元素添加到队列中,如果队列已满则会阻塞等待

    def get(self):
        """从队列头部取出一个元素,如果队列为空则阻塞"""
        return self.queue.get()  # 调用Queue对象的get方法从队列头部取出一个元素,如果队列为空则会阻塞等待

井发队列的实现,以及阻塞井发队列的实现

class BurstQueue:
    def __init__(self, maxsize=0):
        self.queue = Queue(maxsize)

    def put(self, items):
        """将元素列表一次性添加到队列尾部"""
        for item in items:
            self.queue.put(item, block=False)

    def get(self, size):
        """从队列头部一次性取出指定数量的元素"""
        items = []
        for i in range(size):
            try:
                items.append(self.queue.get(block=False))
            except Empty:
                break
        return items


class BlockingBurstQueue:
    def __init__(self, maxsize=0):
        self.queue = Queue(maxsize)

    def put(self, items):
        """将元素列表一次性添加到队列尾部,如果队列已满则阻塞"""
        for item in items:
            self.queue.put(item, block=True)

    def get(self, size):
        """从队列头部一次性取出指定数量的元素,如果队列为空则阻塞"""
        items = []
        for i in range(size):
            items.append(self.queue.get(block=True))
        return items

这里实现的是一个井发队列,它可以一次性将多个元素添加到队列尾部,也可以一次性从队列头部取出指定数量的元素。在实现中,我们依然使用了Python内置的Queue模块,put方法中使用了for循环遍历items列表,并调用Queue对象的put方法将元素逐个添加到队列尾部。在get方法中,我们使用了for循环从队列头部一次性取出指定数量的元素,并将它们存放到一个列表中返回。如果队列中没有足够的元素可以取出,那么get方法会在取够指定数量的元素之前一直等待。
接下来是阻塞井发队列的实现。这个队列在井发队列的基础上,增加了阻塞的特性,如果队列已满则put方法会阻塞等待,如果队列为空则get方法会阻塞等待。在实现中,我们依然使用了Python内置的Queue模块,并将block参数设置为True,表示如果队列已满或者为空,则会阻塞等待。这样就实现了一个阻塞井发队列。

以上便是数据结构有关线性表的相关知识点与实现,见到即是缘分留个关注吧,下期更新树的相关内容。感谢大家的支持!在这里插入图片描述

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
栈(Stack)和队列(Queue)是两种常见的数据结构。 ## 栈 栈是一种后进先出(LIFO,Last In First Out)的数据结构,类似于一叠盘子,后放入的盘子先被取出。 栈的常见操作有: - push(item):将元素压入栈顶 - pop():从栈顶取出元素并返回 - peek():返回栈顶元素,但不弹出 - is_empty():判断栈是否为空 - size():返回栈的元素个数 栈的实现可以使用数组或链表。下面是使用数组实现栈的示例代码: ```python class Stack: def __init__(self): self.items = [] def push(self, item): self.items.append(item) def pop(self): return self.items.pop() def peek(self): return self.items[-1] def is_empty(self): return len(self.items) == 0 def size(self): return len(self.items) ``` 下图展示了栈的操作过程: ![stack](https://user-images.githubusercontent.com/55041489/132706393-8c1c7d3f-5e3d-4f8d-9f3c-2e4cf1c6c0a4.gif) ## 队列 队列是一种先进先出(FIFO,First In First Out)的数据结构,类似于排队等候,先排队的先被服务。 队列的常见操作有: - enqueue(item):将元素加入队尾 - dequeue():弹出队首元素并返回 - is_empty():判断队列是否为空 - size():返回队列的元素个数 队列实现一般使用链表,因为使用数组实现会涉及到元素移动的问题。下面是使用链表实现队列的示例代码: ```python class Node: def __init__(self, value): self.value = value self.next = None class Queue: def __init__(self): self.head = None self.tail = None def enqueue(self, item): node = Node(item) if self.tail: self.tail.next = node else: self.head = node self.tail = node def dequeue(self): if not self.head: raise Exception("Queue is empty") node = self.head self.head = node.next if not self.head: self.tail = None return node.value def is_empty(self): return self.head is None def size(self): size = 0 node = self.head while node: size += 1 node = node.next return size ``` 下图展示了队列的操作过程: ![queue](https://user-images.githubusercontent.com/55041489/132706411-3f3c1a3a-2c47-4c6f-8a0b-7dfb6c4a86af.gif) 总结:栈和队列是两种常用的数据结构,它们具有不同的操作方式和实现方式,可以根据具体的需求选择合适的数据结构
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小翟不会写代码

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

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

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

打赏作者

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

抵扣说明:

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

余额充值