zoukankan      html  css  js  c++  java
  • 数据结构—队列

    数据结构—队列

    1、队列的定义
    队列(Queue)也是一种运算受限的线性表,它的运算限制与栈不同,是两头都有限制。插入仅仅能在表的一端进行(仅仅进不出),而删除仅仅能在表的还有一端进行(仅仅出不进)。同意插入的一端称为队尾(rear),同意删除的一端称为队头 (Front)
    队列模型

    2、队列的操作
    队列的操作原则是先进先出的。所以队列又称作FIFO表(First in First out)
    置空队:InitQueue(Q)
    判队空:QueueEmpty(Q)
    判队满:QueueFull(Q)
    入队:EnQueue(Q,x)
    出队:DeQueue(Q)
    取队头元素:QueueFront(Q)不同于出队,队头元素仍然保留
    3、队列的实现
    1)顺序实现/数组实现


    危急现象:假上溢
    (由于在这里,我们的队列是存储在一个向量空间里,在这一段连续的存储空间中,由一个队列头指针和一个尾指针表示这个队列,当头指针和尾指针指向同一个位置时,队列为空,也就是说,队列是由两个指针中间的元素构成的。

    在队列中,入队和出队并非象现实中,元素一个个地向前移动,走完了就没有了,而是指针在移动,当出队操作时。头指针向前(即向量空间的尾部)添加一个位置。入队时,尾指针向前添加一个位置,在某种情况下,比方说进一个出一个,两个指针就不停地向前移动,直到队列所在向量空间的尾部,这时再入队的话,尾指针就要跑到向量空间外面去了,仅管这时整个向量空间是空的,队列也是空的,却产生了"上溢"现象,这就是假上溢。)
    解决方式:循环队列
    (把向量空间弯起来,形成一个头尾相接的环形,这样,当存于当中的队列头尾指针移到向量空间的上界(尾部)时,再加1的操作(入队或出队)就使指针指向向量的下界。也就是从头開始。)
    怎样区分循环队列是空的还是满的?
    方法1、设立一个bool变量来推断
    方法2、少用一个元素空间,当入队时,先測试入队后尾指针是不是会等于头指针,假设相等则说明对慢了。不许入队了。


    方法3、利用计数器记录队列中元素的总数,随时知道队列的长度了
    參考代码:

       typedef struct QueueRecord
       {
           ElemType elem[MAX_QUEUE] ; 
           int front;//队头指针
           int rear;//队尾指针
           int Size;//队列大小
           ElemetType *Array;
        }QUEUE;
    
        /*操作算法*/
        void InitQueue(*&Q);
        void EnQueue(QUEUE *Q,ElemType elem);
        void DeQueue(QUEUE *Q,ElemType *elem);
        int QueueEmpty(QUEUE Q);
        void GetFront(QUEUE Q,ElemType *elem);
    
        //初始化直接使用结构体指针变量。必须先分配内存地址
        void InitQueue(Queue *&Q)
        {
            Q = (QUEUE *)malloc(sizeof(QUEUE));
            Q.front = Q.rear = -1;
        }
    
        //入队
        void EnQueue(Queue *Q, ElemType elem)
        {
            if((Q->rear+1)% MAX_QUEUE == Q.front)
                exit(OVERFLOW);
            Q.rear = (Q.rear + 1) % MAX_QUEUE;
            Q.elem[Q.rear] = elem;
        }
    
        //出队
        void DeQueue(QUEUE *Q, ElemType *elem)
        {
            if(QueueEmpty(*Q))
                exit(QUEUEEMPTY);
            Q->front = (Q.front+1) % MAX_QUEUE;
            *elem = Q.elem[Q.front];
        }
    
        //获取队列头元素
        void GetFront(QUEUE Q, ElemType *elem)
        {
            if(QueueEmpty(Q))
                exit(QUEUEEMPTY);
            *elem = Q.elem[(Q.front+1) % MAX_QUQUE];
        }
    
        //推断队列是否为空
        int QueueEmpty(QUEUE Q)
        {
            if(Q.front == Q.rear)
                return true;
            return false;
        }
    

    2)链表实现
    參考代码:

    //链式队列的结点的结构
    typedef struct LNode
    {
        ElemType elem;//队列元素类型
        struct LNode *next;//指向后继结点的指针
    }LNode, *LinkList;
    //链式队列
    typedef struct queue
    {
        LinkList front;//对头指针
        LinkList rear;//队尾指针
    }QUEUE;
    //各项算法
    void InitQueue(QUEUE *Q);
    void EnQueue(QUEUE *Q, ElemType elem);
    void DeQueue(QUEUE *Q, ElemType *elem);
    void GetFront(QUEUE Q, ElemType *elem);
    bool QueueEmpty(QUEUE Q);
    
    //初始化队列
    void InitQueue(QUEUE *Q)
    {
        Q->front = (LinkList)malloc(sizeof(LNode));
        if(Q->front == NULL)
            exit(ERROR);
        Q->rear = Q->front;
    }
    
    //入栈
    void EnQueue(QUEUE *Q, ElemType elem)
    {
        Linklist s;
        s = (Linklist)malloc(sizeof(LNode));
        if(!s)
            exit(ERROR);
        s->elem = elem;
        s->next = NULL;
        Q->rear->next = s;
        Q->rear = s;
    }
    //出队
    void DeQueue(QUEUE *Q, ElemType *elem)
    {
        LinkList s;
        if(QueueEmpty(*Q))
            exit(ERROR);
        *elem = Q->front->next->elem;
        s = Q->front->next;
        Q->front->next = s->next;
        free(s);
    }
    //获取对头元素内容
    void GetFront(QUEUE Q, ElemType *elem)
    {
        if(QueueEmpty(Q))
            exit(ERROR);
        *elem = Q->front->next->elem;
    }
    //推断队列Q是否为空
    bool QueueEmpty(QUEUE Q)
    {
        if(Q->front == Q->rear)
            return true;
        return false;
    }
    

    队列的简单应用
    【举例1】模拟打印机缓冲区
    在主机将数据输出到打印机时,会出现主机速度与打印机的打印速度不匹配的问题。

    这时主机就要停下来等待打印机。

    显然,这样会减少主机的使用效率。

    为此人们设想了一种办法:为打印机设置一个打印数据缓冲区,当主机须要打印数据时。先将数据依次写入这个缓冲区,写满后主机转去做其它的事情,而打印机就从缓冲区中依照先进先出的原则依次读取数据并打印,这样做即保证了打印数据的正确性。又提高了主机的使用效率。由此可见,打印机缓冲区实际上就是一个队列结构。


    【举例2】银行排队
    【举例3】CPU分时系统

    在一个带有多个终端的计算机系统中,同一时候有多个用户须要使用CPU执行各自的应用程序,它们分别通过各自的终端向操作系统提出使用CPU的请求。操作系统通常依照每一个请求在时间上的先后顺序,将它们排成一个队列。每次把CPU分配给当前队首的请求用户。即将该用户的应用程序投入执行,当该程序执行完成或用完规定的时间片后,操作系统再将CPU分配给新的队首请求用户,这样即能够满足每一个用户的请求,又能够使CPU正常工作。
    4、C++ STL——queue用法
    queue 模板类的定义在<queue>头文件里。


    与stack 模板类非常相似,queue模板类也须要两个模板參数,一个是元素类型,一个容器类
    型,元素类型是必要的,容器类型是可选的。默觉得deque类型。
    定义queue 对象的演示样例代码例如以下:
    queue<int> q1;
    queue<double> q2;

    queue 的基本操作有:
    入队,如例:q.push(x); 将x 接到队列的末端。


    出队,如例:q.pop(); 弹出队列的第一个元素,注意。并不会返回被弹出元素的值。


    訪问队首元素,如例:q.front(),即最早被压入队列的元素。
    訪问队尾元素,如例:q.back(),即最后被压入队列的元素。


    推断队列空。如例:q.empty(),当队列空时,返回true。
    訪问队列中的元素个数,如例:q.size()

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    【HDOJ】2267 How Many People Can Survive
    【HDOJ】2268 How To Use The Car
    【HDOJ】2266 How Many Equations Can You Find
    【POJ】2278 DNA Sequence
    【ZOJ】3430 Detect the Virus
    【HDOJ】2896 病毒侵袭
    求奇数的乘积
    平方和与立方和
    求数列的和
    水仙花数
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4727049.html
Copyright © 2011-2022 走看看