循环队列

队列

先进先出(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, 然后把原来队里中的内容复制到新的队列中, 但是要保证在新队列中原来元素的位置不能更改
posted @ 2016-10-22 13:06  qlshine  阅读(323)  评论(0编辑  收藏  举报