• [读书笔记]-大话数据结构-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
  • 相关阅读:
    solr7.7.0 添加core (二)
    centos 安装solr7.7+tomcat8.5.31+jdk1.8 环境搭建(一)
    springboot 切面编程 日志模块
    Mysql 优化
    mysql查询某个字段中是否有重复的值
    php for循环字母
    layui.table.toolbar里的内容加判断
    phpmyadmin 导入大文件配置
    解决laravel5.2 使用ajax时的 VerifyCsrfToken问题
    火狐浏览器禁止缓存
  • 原文地址:https://www.cnblogs.com/zhaoxy/p/7804958.html
Copyright © 2020-2023  润新知