队列在日常生活中的应用很广泛,在很多的需要排队的场景中,我们均需要用到队列,队列的结构中,在一端来进行插入,插入的一段称为队尾,在另一端进行删除,删除的一段称为队头。队列是一种先进先出表(FIFO)。
队列的实现中,可以采用顺序存储的方式,也可以采用链式存储的方式。
顺序存储方式中,需要开辟空间,但空间毕竟是有限,尤其在删除操作中,需要移动大量的后者的数据,如果不移动的话,则需要二个变量来指示队首和队尾,front指示队头的存储的元素,rear指示队尾的元素的下一位,当front与rear相等的时候,说明是空队列,但这个会导致一个假溢出的问题,一是队尾的指针的溢出,另一个是前面本身有空位,但却不能应用的问题。
python实现简单的顺序存储的队列
# -*- coding: utf-8 -*-
class Queue_sq_1():
def __init__(self):
self._list = []
self._rear = 0
def is_empty(self):
if self._rear == 0:
return 1
else:
return 0
def insert_one(self, data):
self._list.append(data)
self._rear += 1
def delete_one(self):
for i in range(len(self._list))[1::]:
self._list[i-1] = self._list[i]
self._rear -= 1
def first_data(self):
return self._list[0]
queue = Queue_sq_1()
queue.insert_one(1)
c = queue.first_data()
queue.insert_one(2)
queue.insert_one(3)
queue.delete_one()
a = queue.first_data()
queue.delete_one()
b = queue.first_data()
print a, b, c
python实现二个指针的顺序存储的简单队列
# -*- coding: utf-8 -*-
class Queue_sq_2():
def __init__(self):
self._list = []
self._front = 0
self._rear = 0
def is_empty(self):
if self._front == self._rear:
return 1
else:
return 0
def insert_one(self, data):
self._list.append(data)
self._rear += 1
def delete_one(self):
if self.is_empty() == 1:
print "can not delete the data"
self._front += 1
def first_data(self):
return self._list[self._front]
queue = Queue_sq_2()
queue.insert_one(1)
c = queue.first_data()
queue.insert_one(2)
queue.insert_one(3)
queue.delete_one()
a = queue.first_data()
queue.delete_one()
b = queue.first_data()
print a, b, c
为了解决上述的问题,我们采用首尾相接的循环队列结构。也就是front,rear的变化更加的灵活多变,front可以比rear大,也可以比rear小。在此处采用空一个元素来作为满队列的情况。
1,判断满队列的条件:
(rear + 1)%QueueSize == front来作为满队列的标志
2,队列长度的计算:
(rear - front + QueueSize)% QueueSize
python实现循环队列
# -*- coding: utf-8 -*-
class Queue_sq_round():
def __init__(self):
self._list = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
self._front = 0
self._rear = 0
self._QueueSize = 10
def is_empty(self):
if self._rear == self._front:
return 1
else:
return 0
def is_full(self):
if (self._rear + 1) % self._QueueSize == self._front:
return 1
else:
return 0
def insert_one(self,data):
if self.is_full() == 1:
print "the queue is full,Can not insert the data!"
return False
self._list[self._rear] = data
if self._rear == self._QueueSize - 1:
self._rear = 0
else:
self._rear += 1
def delete_one(self):
if self.is_empty() == 1:
print "the queue is empty,can not delete the data!"
return False
self._list[self._front] = 0
if self._front == 9:
self._front = 0
else:
self._front += 1
def get_length(self):
length = (self._rear - self._front + self._QueueSize) % self._QueueSize
return length
def first_data(self):
if self.is_empty() == 1:
print "Can not get the first data,the queue is empty"
return False
return self._list[self._front]
queue = Queue_sq_round()
queue.is_empty()
queue.insert_one(0)
queue.is_empty()
queue.insert_one(1)
queue.insert_one(2)
queue.insert_one(3)
queue.insert_one(4)
queue.insert_one(5)
queue.insert_one(6)
queue.insert_one(7)
queue.insert_one(8)
queue.insert_one(9)
queue.is_empty()
queue.is_full()
a = queue.first_data()
queue.delete_one()
b = queue.first_data()
print a, b
队列的链式存储方式中,使头指针指向头结点,让尾指针指向队列的尾端,链队列为空的时候,头指针和尾指针均指向头结点。
python实现链队列
# -*- coding: utf-8 -*-
class Node():
def __init__(self, data):
self._data = data
self._next = None
class Queue_link():
def __init__(self):
self._head = Node(data=0)
self._front = self._head
self._rear = self._head
def is_empty(self):
if self._front == self._rear:
return 1
else:
return 0
def insert_one(self, data):
a = Node(data)
self._rear._next = a
self._rear = a
self._head._data += 1
def delete_one(self):
if self.is_empty() == 1:
print "Can not delete the data"
return False
p = self._head._next
self._head._next = p._next
self._head._data -= 1
def first_data(self):
if self.is_empty() == 1:
print "the queue is empty, can not get the first data"
return False
p = self._head._next
return p._data
queue = Queue_link()
queue.is_empty()
queue.insert_one(0)
queue.insert_one(1)
queue.insert_one(2)
a = queue.first_data()
queue.delete_one()
b = queue.first_data()
print a, b
对比循环队列和链队列,二者的基本操作的时间操作均为O(1),但循环序列需要提前申请好空间,使用期间不释放空间,而对于链队列,每次申请和释放节点需要额外的时间开销。循环队列有一个固定的长度,可能会造成资源的浪费或者不足,而链队列则需要一个额外的指针域的空间开销,也可以接受。所以,如果可以确定队列的最大值,使用循环队列,无法预估队列的长度时,使用链队列。