zoukankan      html  css  js  c++  java
  • 队列的顺序存储结构--循环队列

    1 定义
      队列是只允许在一端进行插入操作,另一端进行删除操作的线性表。
      队列是一种先进先出(FIST IN FIRST OUT)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为对头。

    2 队列的顺序存储结构
    (1)队列顺序存储的不足--引出循环队列

        假设一个队列有n个元素,则顺序存储的队列需要建立一个大于n的数组,并把队列的所有元素存储在数组的前n个单元,数组下标为0的一端即为对头。
        所谓的入队,就是在队尾追加一个元素,不需要移动任何元素,所以时间复杂度为O(1).
        队列的出队是在对头,即下标为0的位置,也就意味着,队列中的所有位置都得向前移动,以保证下标为0的位置,即对头不为空。此时时间复杂度为O(n)。

        可是有时候想想,为什么出队列时一定要全部移动呢?如果不限制队列的元素一定要存储在数组的前n个单元,出队的性能就会大大增加。也就是说,队头不需要一定在下标为0的位置。

        为了避免当只有一个元素时,对头和队尾重合使得处理变得麻烦,所以引入两个指针,front指针指向对头元素,rear指针指向队尾元素的下一个元素。这样当front等于rear时,不是队列中有一个元素,而是表示空队列。

        假设数组的长度为5,空队列及初始状态如左图所示,front与rear指针都指向下标为0的位置。当队列中有4个元素时,front指针不变,rear指针指向下标为4的位置。

        此时出队两个元素,则front指针指向下标为2的位置,rear不变。再入队一个元素,front指针不变,此时rear指针移动到数组之外。

        假设这个队列中的总个数不超过5个,但目前如果接着入队的话,会导致数组越界的错误,但是队列在下标为0和1的位置是没有元素的。我们把这种现象叫做“假溢出”。

        为了解决“假溢出”的问题,我们引入循环队列。

    (2)循环队列

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

      继续刚才的例子,将rear指针指向下标为0的位置,就不会导致rear指针指向不明的问题。

      接着入队两个元素,会发现rear指针与front重合了。

      此时问题又来了,刚才说了,当rear等于front时,表示是空队列,现在当队列满时,rear也等于front。那么如何判断队列到底是空的还是满的了?

      解决办法为:当队列空时,判断条件就是rear=front, 当队列满时,我们修改其判断条件,保留一个元素空闲。也就是说,队列满时,数组中还有一个空闲单元。以下两种情况,我们都认为队列已经满了。

      由于rear可能比front大,也可能比front小,所以假设队列的最大尺寸为QueueSize, 队列满的判断条件改为(rear + 1)%QueueSize = front. 队列的长度为(rear - front + QueueSize)% QueueSize.

    循环队列的顺序存储结构为

    typedef int QElemType;
    typedef struct {
        QElemType data[MAXSIZE];
        int rear;            //头指针
        int front;           //尾指针,若队列不为空,指向队尾元素的下一个元素
    }SqQueue;

    循环队列的初始化

    //初始化一个空队列
    Status InitQueue(SqQueue *Q) {
        Q->rear = 0;
        Q->front = 0;
        return OK;
    }

    循环队列求当前队列的长度

    //返回Q的元素个数,也就是队列的当前长度
    int QueueLength(SqQueue Q) {
        return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
    }

    循环队列的入队操作

    //若队列未满,插入元素e为新的队尾元素
    Status insertQueue(SqQueue *Q, QElemType e) {
        if ((Q->rear + 1) % MAXSIZE == Q->front) {    //队满
            return ERROR;
        }
        Q->data[Q->rear] = e;
        Q->rear = (Q->rear + 1) % MAXSIZE;
        return OK;
    }

    循环队列的出队操作

    //若队列不为空,删除Q的对头元素,并用e返回
    Status deleteQueue(SqQueue *Q, QElemType *e) {
        if (Q->rear == Q->front) {                //队空
            return ERROR;
        }
        *e = Q->data[Q->front];
        Q->front = (Q->front + 1) % MAXSIZE
        return OK;
    }
  • 相关阅读:
    20200226 Java IO流——廖雪峰
    20200225 Java 多线程(2)-廖雪峰
    20200225 Java 多线程(1)-廖雪峰
    20200224 尚硅谷ElasticSearch【归档】
    20200224 一 概述
    20200222 尚硅谷Dubbo【归档】
    20200222 四、dubbo原理
    Improved robustness of reinforcement learning policies upon conversion to spiking neuronal network platforms applied to Atari Breakout game
    Reinforcement learning in populations of spiking neurons
    Solving the Distal Reward Problem through Linkage of STDP and Dopamine Signaling
  • 原文地址:https://www.cnblogs.com/muzijie/p/5650187.html
Copyright © 2011-2022 走看看