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;
    }
  • 相关阅读:
    网页鼠标点击特效
    ElementUI 删除 el-table 当前选中行(不是selection列)
    Vue阻止冒泡
    Vue实现选项卡切换
    Vue的条件渲染
    Vue实现勾选后向数组都添加
    Vue实现商城里面多个商品计算,全选,删除
    VUE实现请求数据
    JS实现数组每次只显示5条数据
    移动端分享到微信和QQ
  • 原文地址:https://www.cnblogs.com/muzijie/p/5650187.html
Copyright © 2011-2022 走看看