算法和数据机构学习笔记之队列

算法和数据机构学习笔记之队列

定义:

  • 只允许在一端进行插入操作,而在另一端进行删除的操作的线性表
  • 一种先进先出的线性表
  • 允许插入的一端叫做队尾,允许删除的一端叫做队头

抽象数据类型:

init(初始化操作)
enquene(self,item) 若队列存在,插入新元素item到队列中,并成为队尾元素
dequene(self) 删除队列中队头元素,并返回队头元素

用数组实现队列:

思路:
数组实现队列时,要注意,随着不断进队,出队,head和tail都会持续往后移动。当tail移动到最右边,即使数组中还有空余空间,也无法继续往队列中添加元素了。这时可以用数据搬移。但是如果每一次出队,都要搬移数据,时间复杂度就是0(n)。要让时间复杂度尽可能变小,可以先在元素出队时,不搬移数据。若没有空间,再集中触发一次搬移数据的操作。

from typing import Optional
class ArrayQuene:
    def __init__(self,capacity:int):
        self.capacity=capacity
        self.items=[]
        self.head=0
        self.tail=0
    def enquene(self,item:str):
        if self.tail==self.capacity:
            return False
        else:
            #数据搬移
            for i in range(0,self.tail-self.head):
                self.items[i]=self.items[i+self.head]
            self.tail=self.tail-self.head
            self.head=0
        #插入元素至队尾,队尾后移    
        self.items.insert(self.tail,item)    
        self.tail+=1
        return True    
    def dequene(self):
        # 若栈空
        if self.head==self.tail:
            return None
        #若栈不为空
        else:
            #把队头元素从队头删掉
            item=self.items[self.head]
            self.items.pop(self.head)
            self.head-=1
        return item
    #展示给开发者,用于测试
    def __repr__(self):
        return " ".join(item for item in self.items[self.head:self.tail])
    
if __name__ == "__main__":
    q=ArrayQuene(10)
    for i in range(0,9):
        q.enquene(str(i))
    print (q)    
    q.enquene("3")
    print(q)
    q.dequene()
    print(q)
    print(q.items)    

队列的链式存储结构以及实现:

思路:
入队时,是从链队列尾部添加元素;出队时,从链队列的头部删除元素。入队时,在链表尾部插入结点。如果链表尾部元素为空,那么插入的元素就是第一个元素。出队时,头结点的后继指针出队,将头结点的后继指针改为它后面的结点。

from typing import Optional

class Node:
    
    def __init__(self, data: str, next=None):
        self.data = data
        self.next = next

class LinkedQueue:

    def __init__(self):
        self.head: Optional[Node] = None
        self.tail: Optional[Node] = None
    
    def enqueue(self, value: str):
        new_node = Node(value)
        #如果存在队尾元素
        if self.tail:
            self.tail.next = new_node
        else:
            self.head = new_node
        self.tail = new_node
    
    def dequeue(self) -> Optional[str]:
    #如果存在对头元素
        if self.head:
            value = self.head.data
            self.head = self.head.next
            if not self.head:
                self.tail = None
            return value
    
    def __repr__(self) -> str:
        values = []
        current = self.head
        while current:
            values.append(current.data)
            current = current.next
        return "->".join(value for value in values)


if __name__ == "__main__":
    q = LinkedQueue()
    for i in range(10):
        q.enqueue(str(i))
    print(q)

    for _ in range(3):
        q.dequeue()
    print(q)

循环队列

因为顺序队列需要做数据搬移,时间性能上有较大的的改进空间。循环队列可以弥补顺序队列的不足。当有元素出队有元素进队,使得前面的头指针所指的元素的下标不为0,头结点前还有空位时,后面的元素直接插入头结点前的空位,使得队列头尾相接。
问题在于:当head == tail时,队列为空。那么现在这种情况,如果队列满,我们发现head也可以是head == tail.
所以可以采取空余一个位置的办法。
这种情况下,队列满的条件是(tail+1)%QueneSize=head
长度为(tail+QueneSize-head)%QueneSize

from typing import Optional
from itertools import chain

class CircularQueue:

    def __init__(self, capacity):
        self._items = []
        self._capacity = capacity + 1
        self._head = 0
        self._tail = 0
    
    def enqueue(self, item: str) -> bool:
        if (self._tail + 1) % self._capacity == self._head:
            return False
        
        self._items.append(item)
        self._tail = (self._tail + 1) % self._capacity
        return True
    
    def dequeue(self) -> Optional[str]:
        if self._head != self._tail:
            item = self._items[self._head]
            self._head = (self._head + 1) % self._capacity
            return item
    
    def __repr__(self) -> str:
        if self._tail >= self._head:
            return " ".join(item for item in self._items[self._head : self._tail])
        else:
            return " ".join(item for item in chain(self._items[self._head:], self._items[:self._tail]))

if __name__ == "__main__":
    q = CircularQueue(5)
    for i in range(5):
        q.enqueue(str(i))
    q.dequeue()
    q.dequeue()
    q.enqueue(str(5))
    print(q)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值