数据结构 07-队列概念、分类、Python 中使用列表 list 实现

目  录

1. 队列简介

1.1 队列的概念

1.2 队列的类型

1.2.1 顺序队列

1.2.1 循环队列

1.2.2 双端队列

2. Python 中使用列表 list 实现队列

2.1 顺序队列

2.1.1 顺序队列的常规操作

2.1.2 顺序队列的代码实现

2.2 循环队列的常规操作和代码实现

2.2.1 循环队列的常规操作

2.2.2 循环队列的代码实现

2.3 双端队列

2.3.1 双端队列的常规操作

2.3.2 双端队列的代码实现

1. 队列简介

1.1 队列的概念

        队列可以看成是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。所以可以说,队列是 FIFO 的。队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。

1.2 队列的类型

        队列根据内存地址、删除和插入方式的不同,基本类型可以分为三种,分别是顺序队列、循环队列、双端队列。按照其他方式,还有其他分类,本文先就最简单的展开论述。

1.2.1 顺序队列

        顺序队列,又可以称之为简单队列,可以看成是一种特殊的线性表。在很多语言中是开辟出一片静态的内存,队头随着删除操作而后移,队尾随着插入操作而后移,这时候就会出现内存中有剩余空间(队头删除数据后剩下的空间)无法重新利用,但是整个队列已经无法新插入数据了(队尾的地址要超出这静态内存的容量了)。好在 Python 中没有这个问题。

1.2.1 循环队列

        有些语言中会建立循环队列,即内存尾部(队尾)的指针指向了内存的头指针,这样不断地移动队头、队尾的指针,建立了循环队列,就可以解决 1.2.1 中的问题。

1.2.2 双端队列

        双端队列,又称之为双头队列,即允许从队列的两段(前段和后端)进行插入和删除操作。

2. Python 中使用列表 list 实现队列

        这是一种非常简单方便的方法,因为 列表 list 是可以动态增加长度的,所以不会有溢出问题。

2.1 顺序队列

2.1.1 顺序队列的常规操作

        顺序队列一般需要能实现的基本操作有:

        1)创建顺序队列

        2)入队,即在队列尾部插入数据

        3)出队,即在队列头部删除数据

        4)读取队列头元素

        5)将队列清空

2.1.2 顺序队列的代码实现

        参考:232. 用栈实现队列 - 力扣(LeetCode)

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

实现 MyQueue 类:

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
说明:

你 只能 使用标准的栈操作 —— 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
 

示例 1:

输入:
["MyQueue", "push", "push", "peek", "pop", "empty"]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]

解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
 

提示:

1 <= x <= 9
最多调用 100 次 push、pop、peek 和 empty
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)
 

我的代码实现如下:

class MyQueue:

    def __init__(self):
        self.queue=[]
        self.length=0


    def push(self, x: int) -> None:
        self.queue.append(x)
        self.length+=1
        return(None)


    def pop(self) -> int:
        if(self.length>0):
            tmp=self.queue[0]
            self.queue=self.queue[1:]
            self.length-=1
            return(tmp)
        else:
            return(None)


    def peek(self) -> int:
        if(self.length>0):
            tmp=self.queue[0]
            return(tmp)
        else:
            return(None)


    def empty(self) -> bool:
        if(self.length==0):
            return(True)
        else:
            return(False)

2.2 循环队列的常规操作和代码实现

2.2.1 循环队列的常规操作

        循环队列设计意图一般是为了节省内存空间,虽然 Python 一般不需要自己控制内存,但是它也是可以实现循环队列的设计。其需要能实现的基本操作有:

        1)创建循环队列

        2)入队,即在循环队列尾部插入数据

        3)出队,即在循环队列头部删除数据

        4)读取循环队列头、尾元素

        5)检查循环队列是否为空

        6)检查循环队列是否已满

2.2.2 循环队列的代码实现

        参考:622. 设计循环队列 - 力扣(LeetCode)

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
 

示例:

MyCircularQueue circularQueue = new MyCircularQueue(3); // 设置长度为 3
circularQueue.enQueue(1);  // 返回 true
circularQueue.enQueue(2);  // 返回 true
circularQueue.enQueue(3);  // 返回 true
circularQueue.enQueue(4);  // 返回 false,队列已满
circularQueue.Rear();  // 返回 3
circularQueue.isFull();  // 返回 true
circularQueue.deQueue();  // 返回 true
circularQueue.enQueue(4);  // 返回 true
circularQueue.Rear();  // 返回 4
 

提示:

所有的值都在 0 至 1000 的范围内;
操作数将在 1 至 1000 的范围内;
请不要使用内置的队列库。

我的代码实现如下:

class MyCircularQueue(object):

    def __init__(self, k):
        """
        :type k: int
        """
        self.queue=[]
        self.queue_maxlen=k
        self.head=-1
        self.tail=-1
        self.num=0
        i=0
        while(i<self.queue_maxlen):
            self.queue.append(None)
            i+=1


    def enQueue(self, value):
        """
        :type value: int
        :rtype: bool
        """
        if(self.head==-1 and self.tail==-1 ):
            self.head=0
            self.tail=0
            self.queue[0]=value
            self.num+=1
            return(True)

        if(self.num<self.queue_maxlen):
            self.tail=(self.tail+1)%self.queue_maxlen
            self.queue[self.tail]=value
            self.num+=1
            return(True)
        else:
            return(False)



    def deQueue(self):
        """
        :rtype: bool
        """
        if(self.num==0):
            return(False)
        else:
            self.queue[self.head]=None
            self.head=(self.head+1)%self.queue_maxlen
            self.num-=1
            return(True)

    def Front(self):
        """
        :rtype: int
        """
        if(self.num==0):
            return(-1)
        else:
            return(self.queue[self.head])

    def Rear(self):
        """
        :rtype: int
        """
        if(self.num==0):
            return(-1)
        else:
            return(self.queue[self.tail])


    def isEmpty(self):
        """
        :rtype: bool
        """
        if(self.num==0):
            return(True)
        else:
            return(False)



    def isFull(self):
        """
        :rtype: bool
        """
        if(self.num==self.queue_maxlen):
            return(True)
        else:
            return(False)

2.3 双端队列

2.3.1 双端队列的常规操作

        双端队列设计更加灵活。其需要能实现的基本操作有:

        1)创建双端队列

        2)在队列头部、队列尾部入队,即插入数据

        3)在队列头部、队列尾部出队,即删除数据

        4)读取队列头、尾元素

        5)检查双端队列是否为空

        6)检查双端队列是否已满(如果同时是循环队列的话)

2.3.2 双端队列的代码实现

        参考:641. 设计循环双端队列 - 力扣(LeetCode)

设计实现双端队列。

实现 MyCircularDeque 类:

MyCircularDeque(int k) :构造函数,双端队列最大为 k 。
boolean insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 true ,否则返回 false 。
boolean insertLast() :将一个元素添加到双端队列尾部。如果操作成功返回 true ,否则返回 false 。
boolean deleteFront() :从双端队列头部删除一个元素。 如果操作成功返回 true ,否则返回 false 。
boolean deleteLast() :从双端队列尾部删除一个元素。如果操作成功返回 true ,否则返回 false 。
int getFront() ):从双端队列头部获得一个元素。如果双端队列为空,返回 -1 。
int getRear() :获得双端队列的最后一个元素。 如果双端队列为空,返回 -1 。
boolean isEmpty() :若双端队列为空,则返回 true ,否则返回 false  。
boolean isFull() :若双端队列满了,则返回 true ,否则返回 false 。
 

示例 1:

输入
["MyCircularDeque", "insertLast", "insertLast", "insertFront", "insertFront", "getRear", "isFull", "deleteLast", "insertFront", "getFront"]
[[3], [1], [2], [3], [4], [], [], [], [4], []]
输出
[null, true, true, true, false, 2, true, true, true, 4]

解释
MyCircularDeque circularDeque = new MycircularDeque(3); // 设置容量大小为3
circularDeque.insertLast(1);                    // 返回 true
circularDeque.insertLast(2);                    // 返回 true
circularDeque.insertFront(3);                    // 返回 true
circularDeque.insertFront(4);                    // 已经满了,返回 false
circularDeque.getRear();                  // 返回 2
circularDeque.isFull();                        // 返回 true
circularDeque.deleteLast();                    // 返回 true
circularDeque.insertFront(4);                    // 返回 true
circularDeque.getFront();                // 返回 4
 
 

提示:

1 <= k <= 1000
0 <= value <= 1000
insertFront, insertLast, deleteFront, deleteLast, getFront, getRear, isEmpty, isFull  调用次数不大于 2000 次

我的代码实现如下:

class MyCircularDeque:

    def __init__(self, k: int):
        self.rec=[]
        self.max_len=k
        self.len=0


    def insertFront(self, value: int) -> bool:
        if(self.len<self.max_len):
            self.rec=[value]+self.rec
            self.len+=1
            return(True)
        else:
            return(False)


    def insertLast(self, value: int) -> bool:
        if(self.len<self.max_len):
            self.rec.append(value)
            self.len+=1
            return(True)
        else:
            return(False)

    def deleteFront(self) -> bool:
        if(self.len==0):
            return(False)
        else:
            #tmp=self.rec[0]
            self.rec=self.rec[1:]
            self.len-=1
            return(True)


    def deleteLast(self) -> bool:
        if(self.len==0):
            return(False)
        else:
            #tmp=self.rec[-1]
            self.rec=self.rec[:-1]
            self.len-=1
            return(True)

    def getFront(self) -> int:
        if(self.len==0):
            return(-1)
        else:
            tmp=self.rec[0]
            return(tmp)

    def getRear(self) -> int:
        if(self.len==0):
            return(-1)
        else:
            tmp=self.rec[-1]
            return(tmp)


    def isEmpty(self) -> bool:
        if(self.len==0):
            return(True)
        else:
            return(False)

    def isFull(self) -> bool:
        if(self.len==self.max_len):
            return(True)
        else:
            return(False)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江南野栀子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值