python百题大通关解题记录-堆栈和队列

目录

017使用单个数组实现多个栈

挑战内容

018实现链栈 

挑战内容

019实现一个跟踪其最小元素的栈

挑战内容

020实现包装多个栈的类 

挑战内容

021使用两个栈实现队列

挑战内容

 023实现链式队列

挑战内容


本文题目编译自 Donne Martin 的开源项目

017使用单个数组实现多个栈

使用单个数组实现多个栈,并且实现每个栈入栈和出栈的方法。栈的介绍如下:

  • 栈(stack)是限定仅在表尾进行插入或删除操作的线性表。
  • 栈是一种数据结构,它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后进入的数据在栈顶,需要读数据的时候从栈顶开始弹出数据。

挑战内容

本次挑战中,你需要在 n_stacks.py 文件中补充类 Stacks 的空缺部分。

  • Stacks 类是定义的使用单个数组实现多个栈的类。
  • Stacks 中的 __init__ 方法用于初始化栈,参数 num_stacks 用于指定栈的个数,参数 stack_size 用于指定单个栈的长度。
  • Stacks 中的 abs_index 方法用于寻找进行入栈操作时数据存储的位置,即数组的索引,参数 stack_index 用于指定是第几个栈,它需要返回一个表示数组索引的数字。
  • Stacks 中的 push 方法用于进行入栈操作,参数 stack_index 用于指定是第几个栈,参数 data 用于指定入栈的数据元素,它没有返回值。
  • Stacks 中的 pop 方法用于进行出栈操作,参数 stack_index 用于指定是第几个栈,它需要返回出栈的那个数据元素。
  • 在进行入栈操作时,如果栈已经满了,则需要使用 raise 语句显示 Exception
  • 在进行出栈操作时,如果栈是空的,也需要使用 raise 语句显示 Exception

代码如下:使用stack_index获取数组中的索引,使用数组来存取数据。

class Stacks(object):

    def __init__(self, num_stacks, stack_size):
        self.num_stacks=num_stacks
        self.stack_size=stack_size
        self.stack_pointers=[-1]*self.num_stacks
        self.stack_array=[None]*self.stack_size*self.num_stacks

    def abs_index(self, stack_index):
        return stack_index*self.stack_size+self.stack_pointers[stack_index]

    def push(self, stack_index, data)://先变指针,再写数据
        if self.stack_pointers[stack_index]==self.stack_size-1:
            raise Exception('Full')
        self.stack_pointers[stack_index]+=1
        array_index=self.abs_index(stack_index)
        self.stack_array[array_index]=data

    def pop(self, stack_index)://先取数据,再动指针
        if self.stack_pointers[stack_index]==-1:
            raise Exception('Empty')
        array_index=self.abs_index(stack_index)
        data=self.stack_array[array_index]
        self.stack_array[array_index]=None
        self.stack_pointers[stack_index]-=1
        return data

018实现链栈 

实现链栈入栈,出栈,查看栈顶元素,查看栈是否为空的方法。链栈的介绍如下:

  • 链栈是指采用链接存储结构实现的栈。通常将链表的头部作为栈顶,尾部作为栈底。

挑战内容

本次挑战中,你需要在 stack.py 文件中补充类 Node 和类 Stack 的空缺部分。

  • Node 类是定义的结点。

  • Node 中的 __init__ 方法用于初始化结点,结点包含数据元素 data 和指向下一个结点地址的指针 next

  • Stack 类是定义的链栈。

  • Stack 中的 __init__ 方法用于初始化链栈,参数 top 为栈顶的指针。

  • Stack 中的 push 方法用于进行入栈操作,参数 data 用于指定入栈的数据元素,它没有返回值。

  • Stack 中的 pop 方法用于进行出栈操作,它没有参数,需要返回出栈的那个数据元素。如果栈是空的,返回 None

  • Stack 中的 peek 方法用于查看栈顶元素,它没有参数,需要返回栈顶的数据元素。

  • Stack 中的 is_empty 方法用于查看栈是否为空,它没有参数,需要返回一个布尔值,即 True 或者 False

    代码如下: 

    class Node(object):
    
        def __init__(self, data, next=None):
            self.data=data
            self.next=next
    
    
    class Stack(object):
    
        def __init__(self, top=None):
            self.top=top
    
        def push(self, data):
            self.top=Node(data,self.top)
    
        def pop(self):
            if self.top is None:
                return None
            data=self.top.data
            self.top=self.top.next
            return data
    
        def peek(self):
            return self.top.data if self.top is not None else None
    
        def is_empty(self):
            return self.top is None

    019实现一个跟踪其最小元素的栈

实现栈入栈,出栈,跟踪栈元素最小值的方法。要求如下:

  • 实现一个最小值栈用于存储最小值,如果入栈的元素值比最小值栈的栈顶值小,就将这个值存入最小值栈。
  • 算法运行的时间复杂度为 O(1)O(1)。
  • 假设入栈的元素没有重复值。

挑战内容

本次挑战中,你需要在 stack_min.py 文件中补充类 StackMin 的空缺部分。

  • StackMin 类继承“实现链栈”挑战中的 Stack 类。
  • StackMin 中的 __init__ 方法继承 Stack 类的初始化操作,并且将最小值栈初始化为一个 Stack 类的实例。参数 top 为栈顶的指针。
  • StackMin 中的 peek 方法用于寻找栈元素的最小值,即最小值栈的栈顶值。它没有参数,需要返回栈元素的最小值。如果最小值栈为空,则返回 sys.maxsize
  • StackMin 中的 push 方法继承 Stack 类的入栈操作,并且当入栈的元素值小于最小值栈的栈顶值时,对最小值栈执行入栈操作。参数 data 用于指定入栈的数据元素,它没有返回值。
  • StackMin 中的 pop 方法继承 Stack 类的出栈操作,并且当出栈的元素值是最小值时,对最小值栈执行出栈操作。它没有参数,需要返回出栈的那个数据元素。

代码:super()方法设计目的是用来解决多重继承时父类的查找问题,所以在单重继承中用不用 super 都没关系;但是,使用 super() 是一个好的习惯。一般我们在子类中需要调用父类的方法时才会这么用
super()的好处就是可以避免直接使用父类的名字.

import sys


class StackMin(Stack):

    def __init__(self, top=None):
        super(StackMin, self).__init__(top)//调用父类方法时使用
        self.stack_of_mins = Stack()

    def minimum(self):
        if self.stack_of_mins.top is None:
            return sys.maxsize
        else:
            return self.stack_of_mins.peek()

    def push(self, data):
        super(StackMin, self).push(data)
        if data < self.minimum():
            self.stack_of_mins.push(data)

    def pop(self):
        data = super(StackMin, self).pop()
        if data == self.minimum():
            self.stack_of_mins.pop()
        return data

020实现包装多个栈的类 

实现一种数据结构 SetOfStack,它由多个栈组成,其中每个栈的容量限制为 indiv_stack_capacity,当前一个栈填满时,新建一个栈。

挑战内容

本次挑战中,你需要在 set_of_stacks.py 文件中补充类 StackWithCapacity 和 SetOfStacks 的空缺部分。

  • StackWithCapacity 类继承“实现链栈”挑战中的 Stack 类。

  • StackWithCapacity 中的 __init__ 方法继承 Stack 类的初始化操作。参数 top 为栈顶的指针,参数 capacity 用于指定栈的容量,即栈的长度。

  • StackWithCapacity 中的 push 方法继承 Stack 类的入栈操作,参数 data 用于指定入栈数据元素,它没有返回值。如果栈已经满了,需要使用 raise 语句显示 Exception

  • StackWithCapacity 中的 pop 方法继承 Stack 类的出栈操作,它没有参数,需要返回出栈的那个数据元素。

  • StackWithCapacity 中的 is_full 方法用于查看栈是否已满,它没有参数,需要返回一个布尔值,即 True 或者 False

  • StackWithCapacity 中的 is_empty 方法用于查看栈是否为空,它没有参数,需要返回一个布尔值,即 True 或者 False

  • SetOfStacks 类是定义的包装栈的类。

  • SetOfStacks 中的 __init__ 方法用于初始化,参数 indiv_stack_capacity 用于指定单个栈的容量。

  • SetOfStacks 中的 push 方法用于进行入栈操作,参数 data 用于指定入栈的数据元素,它没有返回值。当前一个栈填满时,新建一个栈。

  • SetOfStacks 中的 pop 方法用于进行出栈操作,它没有参数,需要返回出栈的那个数据元素。当栈中没有元素时,返回 None

代码:综合运用

from stack import Stack


class StackWithCapacity(Stack)://固定容量的链栈类,使用父类方法用super函数

    def __init__(self, top=None, capacity=10):
        super(StackWithCapacity,self).__init__(top)
        self.capacity=capacity
        self.num_items=0//对节点进行计数,并用于判断栈的空满

    def push(self, data):
        if self.is_full():
            raise Exception('full')
        super(StackWithCapacity,self).push(data)
        self.num_items+=1//节点数加一

    def pop(self):
        if self.is_empty():
            return
        data=super(StackWithCapacity,self).pop()
        self.num_items-=1//节点数减一
        return data

    def is_full(self):
        return self.num_items==self.capacity

    def is_empty(self):
        return self.num_items==0


class SetOfStacks(object):

    def __init__(self, indiv_stack_capacity):
        self.indiv_stack_capacity=indiv_stack_capacity
        self.stacks=[]//建立列表(数组)存储各个容量栈
        self.last_stack=None//表示当前栈的状态,此时没有加入列表

    def push(self, data):
        if self.last_stack is None or self.last_stack.is_full()://无状态(初始状态和元素取完返回的初始状态)或满状态时,生成固定容量链栈
            self.last_stack=StackWithCapacity(None,self.indiv_stack_capacity)
            self.stacks.append(self.last_stack)//加入新生成的固定容量链栈
        self.last_stack.push(data)

    def pop(self):
        if self.last_stack is None:
            return None
        data=self.last_stack.pop()
        if self.last_stack.is_empty():
            self.stacks.pop()//弹出被取空的固定容量链栈
            self.last_stack=self.stacks[-1] if self.stacks else None//列表为空则回到无类型状态
        return data

021使用两个栈实现队列

使用两个栈实现队列。队列的介绍如下:

  • 队列和栈一样,也是一种对数据的"存"和"取"有严格要求的线性存储结构。
  • 队列只允许在表的前端进行删除操作,而在表的后端进行插入操作。进行插入操作的端称为队尾,进行删除操作的端称为队头。

挑战内容

本次挑战中,你需要在 queue_from_stacks.py 文件中补充类 QueueFromStacks 的空缺部分。

  • QueueFromStacks 使用两个栈实现队列类。
  • QueueFromStacks 中的 __init__ 方法使用两个栈来进行初始化。
  • QueueFromStacks 中的 shift_stacks 方法用于将一个栈的元素依次弹出并插入另一个栈中,参数 source 用于指定需要弹出元素的栈,参数 destination 用于指定入用于插入元素的栈。
  • QueueFromStacks 中的 enqueue 方法用于进行入队操作,参数 data 用于指定入队的数据元素,它没有返回值。
  • QueueFromStacks 中的 dequeue 方法用于进行出队操作,它没有参数,需要返回出队的那个数据元素。

原理:双栈栈底对栈底,左栈的栈顶进行入队操作,右栈的栈顶进行出队操作。显然,如果不把左栈的数据移入右栈,必然出现左栈多而右栈空的情形。解决方案:入队时把右栈数据全部移入左栈(右栈栈顶变成左栈栈底),出栈时把左栈数据全部移入右栈 (左栈栈顶变成右栈栈底)

代码:

from stack import Stack


class QueueFromStacks(object):

    def __init__(self):
        self.left_stack=Stack()
        self.right_stack=Stack()

    def shift_stacks(self, source, destination)://dastination是执行操作的栈,初始保持空,获取另一个栈的全部数据(另一个栈变成空)
        while source.peek() is not None:
            destination.push(source.pop())

    def enqueue(self, data):
        self.shift_stacks(self.right_stack,self.left_stack)
        self.left_stack.push(data)

    def dequeue(self):
        self.shift_stacks(self.left_stack,self.right_stack)
        
        return self.right_stack.pop()

 023实现链式队列

实现链式队列入队,出队的方法。链式队列的介绍如下:

  • 链式队列是使用链表实现的队列存储结构。

 

挑战内容

本次挑战中,你需要在 queue_list.py 文件中补充类 Node 和类 Queue 的空缺部分。

  • Node 类是定义的结点。

  • Node 中的 __init__ 方法用于初始化结点,结点包含数据元素 data 和指向下一个结点地址的指针 next

  • Queue 类是定义的链栈。

  • Queue 中的 __init__ 方法用于初始化链式队列。

  • Queue 中的 enqueue 方法用于进行入队操作,参数 data 用于指定入队的数据元素,它没有返回值。

  • Queue 中的 dequeue 方法用于进行出队操作,它没有参数,需要返回出队的那个数据元素。如果队列是空的,返回 None

 代码:(基础扫盲)

class Node(object):

    def __init__(self, data):
        self.data=data
        self.next=next

class Queue(object):

    def __init__(self):
        self.head=None
        self.tail=None

    def enqueue(self, data):
        node=Node(data)
        if self.head is None and self.tail is None:
            self.head=node
            self.tail=node
        else:
            self.tail.next=node
            self.tail=node

    def dequeue(self):
        if self.head is None and self.tail is None:
            return None
        data=self.head.data
        if self.head==self.tail:
            self.head=None
            self.tail=None
        else:
            self.head=self.head.next
        return data

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值