栈 队列 数组

本文详细介绍了栈的类型定义、基本操作,包括Push和Pop,并探讨了数组和链表实现栈的优缺点。接着,文章阐述了队列的特性,以及数组和链表实现队列的方法和对比。最后,提到了数组在Python中的应用和动态扩容的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈的类型定义

在这里插入图片描述

栈的基本操作

Push(&S,e)

  • 初始条件:栈S已存在
  • 操作结果:插入元素e为新的栈顶元素。

Pop(&S,&e)

  • 初始条件:栈已存在且非空
  • 操作结果:删除S的栈顶元素,并用e返回其值。

数组实现栈

在这里插入图片描述

class MyStack(object):
    """模拟栈"""

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

    def is_empty(self):
        """判断是否为空"""
        return self.items == []

    def size(self):
        """返回栈的大小"""
        return len(self.items)

    def push(self, item):
        """压栈(加入元素)"""
        self.items.append(item)


    def pop(self):
        """弹栈(弹出元素)"""
        if len(self.items)>0:
            return self.items.pop()
        else:
            print("栈已经为空")
            return None

    def top(self):
        """返回栈顶元素"""
        if not self.is_empty():
            return self.items[len(self.items) - 1]
        else:
            return None
s = MyStack()
s.push(4)
print("栈顶元素为:"+str(s.top()))
print("栈大小为:"+str(s.size()))
s.pop()
print("弹栈成功")
s.pop()
"""
栈顶元素为:4
栈大小为:1
弹栈成功
栈已经为空

用链表实现栈

在这里插入图片描述
如图,压栈操作就是将新元素放到链表的首部,见第二个数据域的(1)、(2)操作,而弹栈只需要删除链表的第一个元素就可以了,具体操作见(3)。然后我们可以写出代码:

class LNode(object):
    def __init__(self,x):
        """创建节点"""
        self.data = x
        self.next = None

class MyStack(object):
    def __init__(self):
        """创建栈顶"""
        # pHead = LNode()
        self.data = None
        self.next = None

    def is_empty(self):
        """判断是否为空"""
        if self.next == None:
            return True
        return False

    def size(self):
        """返回栈的大小"""
        size=0
        p = self.next
        while p != None:
        # while p is not None:
            p = p.next
            size += 1
        return size

    def push(self, element):
        """压栈(加入元素)"""
        p = LNode(x=element)
        p.data = element
        p.next = self.next
        self.next = p

    def pop(self):
        """弹栈(弹出元素)"""
        if self.next != None:
            p = self.next
            self.next = p.next
            return p.data
        print("栈已经为空")
        return None

    def top(self):
        """返回栈顶元素"""
        if self.next != None:
            return self.next.data
        print("栈已经为空")
        return None

if __name__ == '__main__':
    s = MyStack()
    s.push(1)
    print("栈顶元素为:" + str(s.top()))
    print("栈大小为:" + str(s.size()))
    s.pop()
    print("弹栈成功")
    s.pop()

两种方法的对比

  1. 采用数组实现栈的优点:一个元素值占用一个存储空间;它的缺点为:如果初始化申请的存储空间太大,会造成空间的浪费,如果申请的存储空间太小,后期会经常需要扩充存储空间,扩充存储空间是个费时的操作,这样会造成性能的下降
  2. 采用链表实现栈的优点是:使用灵活方便,只有在需要的时候才会申请空间,它的缺点为:除了要存储元素外,还需要额外的存储空间存储指针信息。

队列

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出的(First In First Out)的线性表,简称FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作!假设队列是q=(a1,a2,……,an),那么a1就是队头元素,而an是队尾元素。这样我们就可以删除时,总是从a1开始,而插入时,总是在队列最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然排在队伍最后。

用数组实现队列

下面给出了一种最简单的实现方式,用front来记录队列首元素的位置,用rear来记录队列尾元素往后一个位置。入队列的时候只需要将待入队列放入下标为rear位置,然后同时执行rear+,那么出队列就是front+。
在这里插入图片描述

class MyQueue(object):
    """队列"""
    def __init__(self):
        self.items = []
        self.front = 0  # 队列头
        self.rear = 0   # 队列尾

    def is_empty(self):
        """判断队列是否为空"""
        return self.items == self.rear

    def enQueue(self, item):
        """进队列,从队尾加入"""
        self.items.append(item)
        self.rear += 1
        # self.items.insert(0,item)     # 从对头进

    def deQueue(self):
        """出队列,从队头出"""
        if self.rear > self.front:
            self.front += 1
        else:
            print("队列已经为空")
        # return self.items.pop()   # 从对尾出

    def getFront(self):
        if self.is_empty():
            return None
        return self.items[self.front]

    def getBack(self):
        if self.is_empty():
            return None
        return self.items[self.rear-1]

    def size(self):
        """返回大小"""
        return self.rear - self.front
        # return len(self.items)	# 看大小
queue = MyQueue()
queue.enQueue(1)
queue.enQueue(2)

print("队列头元素为:"+str(queue.getFront()))
print("队列尾元素为:"+str(queue.getBack()))
print("队列的大小为:"+str(queue.size()))

queue.deQueue()
# queue.deQueue()
print("队列头元素为:"+str(queue.getFront()))
print("队列尾元素为:"+str(queue.getBack()))
print("队列的大小为:"+str(queue.size()))
"""
队列头元素为:1
队列尾元素为:2
队列的大小为:2
队列头元素为:2
队列尾元素为:2
队列的大小为:1
"""

用链表实现队列

采用链表实现队列的方法与实现栈的方法类似,分别用两个指针指向队列的首元素与尾元素,而用pHead来指向队列的首元素,用pEnd来指向队列的尾元素。

在这里插入图片描述

class LNode(object):
    def __init__(self,x):
        self.data = x
        self.next = None

class MyQueue(object):
    def __init__(self):
        """分配头结点"""
        self.pHead = None
        self.pEnd = None

    def is_empty(self):
        """判断是否为空"""
        if self.pHead == None:
            return True
        return False

    def size(self):
        """获取队列的大小"""
        size=0
        p = self.pHead
        while p != None:
        # while p is not None:
            p = p.next
            size += 1
        return size

    def enQueue(self, element):
        """入队列,从队尾加"""
        p = LNode(element)
        p.data = element
        p.next = None
        if self.pHead == None:
            self.pHead = self.pEnd=p
        else:
            self.pEnd.next = p
            self.pEnd = p

    def deQueue(self):
        """出队列,删除首元素"""
        if self.pHead == None:
            print("出队列失败,队列已经为空")
        self.pHead = self.pHead.next
        if self.pHead == None:
            self.pEnd = None

    def getFront(self):
        """返回队列首元素"""
        if self.pHead == None:
            print("获取队列首元素失败,队列已经为空")
            return None
        return self.pHead.data

    def getBack(self):
    	"""返回队列尾元素"""
        if self.pEnd == None:
            print("获取队列尾元素失败,队列已经为空")
            return None
        return self.pEnd.data
queue = MyQueue()
queue.enQueue(1)
queue.enQueue(2)

print("队列头元素为:"+str(queue.getFront()))
print("队列尾元素为:"+str(queue.getBack()))
print("队列的大小为:"+str(queue.size()))

queue.deQueue()
print("队列头元素为:"+str(queue.getFront()))
print("队列尾元素为:"+str(queue.getBack()))
print("队列的大小为:"+str(queue.size()))
"""
队列头元素为:1
队列尾元素为:2
队列的大小为:2
队列头元素为:2
队列尾元素为:2
队列的大小为:1
"""


两种方法的对比

和栈中的优缺点类似,但与栈不同的是,对于队列,用链表的方式比数组更好,因为指针空间在这里的发挥空间更大。

数组

python的基础模块中是没有数组这种数据结构的,用了列表来代替。

关于数组的动态扩容以及增删改查

这个问题其实在python中是不用和C一样大费周章的,python提供的list和字典是可变类型,就像我上面提到的,本身就是一个过度分配的动态数组。所以它的增删改查,我大概画了一个流程图,可以完成基本的所有操作,而如果想要了解底层编译方式,就需要查看CPython解释器了解它的组成,我找到了一篇译文,可以参考如下链接,以及我画的思维导图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值