zoukankan      html  css  js  c++  java
  • 循环队列

    队列

    先进先出(FIFO)结构
    不管是还是队列, 必须尽可能以效率最大化的方式实现, 如: 添加元素在列表末尾
    队列要实现的需求

    - 创建空队列
    - is_empty    判断是否为空
    - enqueue     入队
    - dequeue     出对
    - peek        查看队列里最早进入的元素但是不删除
    

    由于队列先进先出的特殊性, 在使用list实现的时候, 总会有一个操作出现O(n)的时间损耗, 所以采用循环队列的方式, 即先初始化一个固定大小的空间, 若插入元素发现空间不够时自动扩大空间

    • 普通队列:
      如果采用python的list结构来简单实现一段添加,一段弹出, 必定会出现添加或删除的时间复杂度是O(n)
    • 循环队列
      能保证空间得到有效利用, 同时保证插入弹出的时间复杂度都是O(1)

    下例采用循环队列的方式实现

    #!/usr/bin/env python
    # coding:utf-8
    
    class Queue:
        def __init__(self, init_len=8):    # 默认存储区有8个位置存储
            self._len = init_len           # 存储区长度
            self._elems = [0]*init_len     # 存放队列元素
            self._head = 0                 # 表头元素下标, 弹出元素时以该下表为准
            self._num = 0                  # 队列中实际元素个数
    
        def enqueue(self, e):
            """入队"""
            if self._num == self._len:
                self.__extend()
            self._elems[(self._head+self._num)%self._len] = e
            self._num += 1
    
        def dequeue(self):
            """出队"""
            if self._num == 0:
                print '队列为空'
                return
            e = self._elems[self._head]
            self._head = (self._head+1)%self._len
            self._num -= 1
            return e
    
        def __extend(self):
            """扩大存储区容量"""
            old_len = self._len
            self._len *= 2
            new_elems = [0]*self._len
            for i in range(old_len):
                new_elems[i] = self._elems[(self._head+i)%old_len]
            self._elems, self._head = new_elems, 0
    
        def is_empty(self):
            return self._num == 0
    
        def peek(self):
            """取出队首元素但不删除"""
            if self._num == 0:
                print '队列为空'
                return
            return self._elems[self._head]
    
    
    
    if __name__ == '__main__':
        q = Queue()
        for i in range(10):
            q.enqueue(i)
        for i in range(10):
            print q.dequeue()
        print q.is_empty()
    
    
    • 入队:
      用num来做要插入元素的下标, 每进入一个元素num+1, 直到队列满, 拓展空间
    • 出队:
      用head来做要弹出元素的下标, 每弹出一个, num-1, head=(head+1)%len
    • 拓展空间:
      这里拓展倍数是2, 然后把原来队里中的内容复制到新的队列中, 但是要保证在新队列中原来元素的位置不能更改
  • 相关阅读:
    java虚拟机之垃圾回收机制
    java虚拟机之JVM体系结构
    java虚拟机之JVM生命周期
    删除链表中重复的结点
    (二十一)java多线程之Executors
    (十八)java多线程之Callable Future
    (十六)java多线程之优先队列PriorityBlockingQueue
    (十九)java多线程之ForkJoinPool
    (二十)java多线程之ScheduledThreadPoolExecutor
    (六)java多线程之ReadWriteLock
  • 原文地址:https://www.cnblogs.com/qlshine/p/5987365.html
Copyright © 2011-2022 走看看