[读书笔记]-大话数据结构-4-栈与队列(二)-队列

队列的定义

    队列(queue)是只允许在一端进行拆入操作,而在另一端进行删除操作的线性表。队列是一种先进先出(First In First Out)的线性表,简称FIFO允许插入的一段称为队尾,允许删除的一端称为队头

队列的应用非常频繁,例如排队,键盘输入到显示器输出等。

队列的抽象数据类型

ADT 队列(Queue)
Data
    '''同线性表。元素具有相同的类型,相邻元素具有前驱和后继关系。'''
Operation 
    InitQueue(*Q):'''初始化操作,建立一个空队列Q。'''
    DestroyQueue(*Q):'''若队列Q存在,则销毁它'''
    ClearQueue(*Q):'''将队列Q清空'''
    QueueEmpty(Q):'''若队列Q为空,返回true,否则返回false'''
    GetHead(Q,*e):'''若队列Q存在且非空,用e返回Q的队头元素。'''
    EnQueue(*Q,e):'''若队列Q存在,插入新元素e插入到Q中并成为队尾元素。'''
    DeQueue(*Q,*e):'''删除队列Q中队头元素,并用e返回其值。'''
    QueueLength(Q):'''返回队列Q的元素个数。'''
endADT

循环队列

当用线性表表示队列时,为了避免队列元素的大量移动(队头删除元素时),一般引入两个指针,front指向队头元素,rear指向队尾元素的下一个位置,这样,拆入始终在rear指针处进行,删除始终在front指针处进行;当front等于rear时,此队列为空队列。但是这样会产生另外一个问题,列队经过一些拆入和删除操作之后,rear指针可能发生数值越界,但数值的另一端还有空闲,这种现象叫做假溢出。

 

解决假溢出的办法就是后面满了,再从头开始,也就是头尾相接的循环。我们把队列的这种头尾相接的顺序存储结构称为循环队列。如下图所示

    此时会产生另外一个问题,当rear=front时,有可能表示队满,也可能表示队空,为了区分这种情况有两种解决方案

  • 多设置一个flag变量,当rear=front,且flag=0时,表示队列空。当rear=front,且flag=1时表示队满
  • 让队列始终保留一个空元素,也就是,当rear=front时,队列空。当队列仅剩一个空闲元素时,队列慢,所以以下两种情况都表示队列满

循环队列的Python实现

class SqQueue(object):
    def __init__(self,size=20):
        self.data=[None for i in range(size)]
        self.size=size
        self.front=0
        self.rear=0

循环队列的插入操作

    def EnQueue(self,e):#将e插入队列
        if (self.rear+1)%self.size ==self.front:  #队列满
            return 0
        self.data[self.rear]=e   #当前元素赋值给e
        self.rear=(self.rear+1)%self.size  #rear指向下一个
        return 1

循环队列的删除操作

    def DeQueue(self):
        if self.rear==self.front:  #队空
            return None
        e=self.data[self.front]  #获取队头元素
        self.data[self.front]=None   #删除队头元素
        self.front=(self.front+1)%self.front  #头指针往前移动一位
        return e

循环队列的完整代码

class SqQueue(object):
    def __init__(self,size=20):
        self.data=[None for i in range(size)]
        self.size=size
        self.front=0
        self.rear=0
    
    def QueueLength(self):  #返回队列的长度
        return (self.rear-self.front+self.size)%self.size
    
    def EnQueue(self,e):#将e插入队列
        if (self.rear+1)%self.size ==self.front:  #队列满
            return 0
        self.data[self.rear]=e   #当前元素赋值给e
        self.rear=(self.rear+1)%self.size  #rear指向下一个
        return 1
    
    def DeQueue(self):
        if self.rear==self.front:  #队空
            return None
        e=self.data[self.front]  #获取队头元素
        self.data[self.front]=None   #删除队头元素
        self.front=(self.front+1)%self.front  #头指针往前移动一位
        return e
    def ClearQueue(*Q):#将队列清空
        while self.front!=self.rear:  #当队列不空时
            self.data[self.front]=None   #删除对头元素,队头前移一位
            self.front=(self.front+1)%self.size
    def QueueEmpty(self):#若队列Q为空,返回true,否则返回false
        return self.front==self.rear
    def GetHead(self): #若队列Q存在且非空,用e返回Q的队头元素
        return self.data[self.front] #返回当前元素,若队列为空,返回None
    
View Code

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

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出,我们把它简称连队列。

当front和rear都指向头结点时,表示连队列为空。

链队列的实现代码如下:

class LinkQueue(object):
    def __init__(self):  #生成一个空的链队列
        self.front=Node(0)   #头节点,保存元素的个数
        self.rear=self.front
    
    def QueueLength(self):  #返回队列的长度
        return self.count

队列的链式存储结构——入队操作

    def EnQueue(self,e):  #将e插入队列
        p=Node(e)  #待拆入节点
        self.rear.next=p  #尾节点下一个节点指向p
        self.rear=p     #尾指针移到p
        self.front.data+=1  #节点个数+1

队列的链式存储结构——出队操作

    def DeQueue(self):
        if self.rear==self.front:return None #如果链表为空
        p=self.front.next  #待删除
        e=p.data
        self.front.next=p.next  #头结点的下一个节点直接指向p的下个节点
        if self.rear==p:  #如果删除的是尾节点
            self.rear=self.front  #维指针指向头节点
        self.front.data-=1
        return e

链队列的完整代码

 

class Node(object):   #定义链表节点
    def __init__(self,data=None):
        self.data=data
        self.next=None        
        
class LinkQueue(object):
    def __init__(self):  #生成一个空的链队列
        self.front=Node(0)   #头节点,保存元素的个数
        self.rear=self.front
    
    def QueueLength(self):  #返回队列的长度
        return self.count
    
    def EnQueue(self,e):  #将e插入队列
        p=Node(e)  #待拆入节点
        self.rear.next=p  #尾节点下一个节点指向p
        self.rear=p     #尾指针移到p
        self.front.data+=1  #节点个数+1
    
    def DeQueue(self):
        if self.rear==self.front:return None #如果链表为空
        p=self.front.next  #待删除
        e=p.data
        self.front.next=p.next  #头结点的下一个节点直接指向p的下个节点
        if self.rear==p:  #如果删除的是尾节点
            self.rear=self.front  #维指针指向头节点
        self.front.data-=1
        return e
        
    def ClearQueue(*Q):#将队列清空
        self.front=Node(0)  
        self.rear=self.front
        
    def QueueEmpty(self):#若队列Q为空,返回true,否则返回false
        return self.front==self.rear
    
    def GetHead(self): #若队列Q存在且非空,用e返回Q的队头元素
        if self.front.next==None:return None
        else: return self.front.next.data
                
View Code

 

posted @ 2017-11-08 19:00  zhaoxianyu  阅读(317)  评论(0编辑  收藏  举报