• 5.数据结构---队列


    一、队列

    1.队列类型

    • FIFO:先进先出
    • LIFO:后进先出(等同于栈)
    • 优先级队列
    • 双端队列:LIFO和FIFO结合,可以从队首和队尾添加和删除元素
    • 循环队列:队首和队尾相连(可用来解决假溢出)

    2.Python自带Queue模块【线程不安全,需加锁】

    支持三种队列类型:

    • FIFO(queue.queue)
    • LIFO(queue.LifoQueue)
    • 优先级队列(queue.PriorityQueue)【优先级队列越低越先出来】【堆】
    FIFO:import queue
    创建一个队列长度为10的对象:q=queue.queue(maxsize=10)
    队尾插入数据x:q.put(x)
    队首删除数据:q.get(),并返回该数据
    返回队列的大小:q.qsize()
    判断队列是否为空:q.empty(),若为空则返回True,反之则FALSE
    判断是否为满:q.full与maxsize相呼应   

    3.Python自带Deque模块【线程安全,因为GIL】

    支持双端队列

    (1)新建一个deque对象:q=deque('abcdefgh'),或者创建一个大小为5的队列q=deque(5)
    (1)q.appendleft(x):在列表左侧插入【O(1)】
    (2)q.popleft():弹出列表左侧的值【O(1)】
    (3)extendleft:在左侧扩展【O(k)】
    (4)q.append(x):在列表右侧插入【O(1)】
    (5)q.pop():弹出列表右侧的值【O(1)】
    (6)extend:在右侧扩展【O(k)】
    (7)q.rotate(-n):将左端的n个元素移动到右端【O(k)】
       q.rotate(n):将右端的n个元素移动到左端
       q=deque('abcdef')
       q.rotate(-2)
       print(q)//deque(['c','d','e','f','a','b'])
       q.rotate(2)
       print(q)//deque(['e','f','a','b','c','d'])
    (8)q.remove('c'):删除一个指定元素【O(n)】
    (9)q.clear():清空链表所有元素,使其长度为0
    (10)q.reverse():将队列反转
    (11)q.count(x):返回q中x的数量
    (12)len(q):返回q的长度

    4.循环队列

    队尾出来进队首,双端队列的rotate可以实现循环队列。

    二、算法

    1.两个队列实现栈

    题目:使用队列实现栈的下列操作:
      push(x) -- 元素 x 入栈
      pop() -- 移除栈顶元素
      top() -- 获取栈顶元素
      empty() -- 返回栈是否为空
    思路:

      插入:直接在非空的queue中添加新元素

      删除:将一个非空的queue中的数依次从队首到队尾放入空的queue中,直到只剩下一个数,将最后一个数弹出。

    class MyQueue (object):
        def __init__(self):
            self.stack1 = []
            self.stack2 = []
    
        def push(self, x):
            self.stack1.append(x)
    
        def pop(self):
            if self.stack2 != []: # 栈2不为空
                self.stack2.pop()
            elif self.stack2 == [] and self.stack1 != []:
                    while self.stack1 != []:
                        tmp = self.stack1[-1]
                        self.stack1.pop()
                        self.stack2.append(tmp)
                    self.stack2.pop()
            else: # 栈2为空,栈1为空
                print('query is empty')
    
        def top(self):
            return self.stack1[-1]
    
        def empty(self):
            if len(self.stack1) == 0 and len(self.stack2) == 0:
                return True
            else:
                return False
    
    queue = MyQueue()
    queue.push(1)
    queue.push(2)
    queue.pop()
    queue.push(3)
    print(queue)
    

      

    2.两个栈实现队列

    题目:使用栈实现队列的下列操作:

      push(x) -- 将一个元素放入队列的尾部。
      pop() -- 从队列首部移除元素。
      peek() -- 返回队列首部的元素。
      empty() -- 返回队列是否为空。

    思路:        

      插入:在stack1中添加新元素

      删除:删除元素前,先判断stack2是否为空,如果不为空,直接弹出stack2;否则,将stack1中的所有元素全部放入stack2中,再弹出栈顶元素

    class MyQueue(object):
        def __init__(self):
            self.queue1 = []
            self.queue2 = []
    
        def push(self, x):
            if len(self.queue2) == 0:
                self.queue1.append(x)
            if len(self.queue1) == 0:
                self.queue2.append(x)
    
        def pop(self):
            # 将queue的数放入另一个queue中,然后将当前queue里面的数一个个放入另一个queue,直到当前queue的长度为1时,删除当前queue最后一个数
            if len(self.queue1) != 0 and len(self.queue2) == 0:
                while len(self.queue1) != 1:
                    tmp = self.queue1[-1]
                    self.queue1.pop()
                    self.queue2.append(tmp)
            else:
                while len(self.queue2) != 1:
                    tmp = self.queue2[-1]
                    self.queue2.pop()
                    self.queue1.append(tmp)
    
        def peek(self):
            if len(self.queue1) == 0:
                return self.queue2[-1]
            else:
                return self.queue1[-1]
    
        def empty(self):
            if len(self.queue1) == 0 and len(self.queue2) == 0:
                return True
            else:
                return False
    
    Queue = MyQueue()
    Queue.push(1)
    Queue.push(2)
    print(Queue.peek())
    Queue.pop()
    print(Queue)

    3.报数淘汰

    '''
    下面的例子是用queue中的FIFO实现一个功能,6个人传土豆,每数到7就淘汰手中有土豆的人,直到最后只剩一个人。
    '''
    
    # 循环队列,num一定要比人数多
    import queue
    def hotpotato(namelist,num):
        que=queue.Queue(len(namelist))
        for name in namelist:
            que.put(name)
        while que.qsize()>1:
            for item in range(num-1):
                que.put(que.get()) # put队尾插入,get队首删除
            que.get()
        return que.get()
    
    namelist=['a','b','c','d','e']
    print(hotpotato(namelist,7))
    

      

    参考文献:

    【1】Python数据结构2-----队列和堆 - Lee_yl - 博客园

  • 相关阅读:
    函数基础
    全局变量与类似配置文件的模块文件
    global语句(python学习手册422页)
    作用域实例
    变量名解析:LEGB原则
    作用域
    第三方库安装方法
    s[-1]和s[len(s)-1]
    查找特定后缀的文件
    logging日志管理-将日志写入文件
  • 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/11653235.html
Copyright © 2020-2023  润新知