专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

顺序存储队列

1.队列的定义

队列(queue)是只允许在一端(队尾)进行插入操作,在另一端(队头)进行删除操作的线性表。遵循先进先出。

51_1.png

2.顺序存储队列的问题

2、1 时间复杂度

51_2.png

假设一个队列,当我们往队列中添加数据时,即在下标5的位置追加一个元素a6,不用移动任何元素,时间复杂度为O(1),

那么当我们从队列中删除数据时,即在队头删除元素a1,需要将后续元素向前移动,以保证队列的队头还在下标为0的位置,那么它的时间复杂度就是O(n),则出队的性能就会大大增加。

51_3.png

2、2、假溢出

为避免出队的问题,不再以下标为0固定为队头,引入了两个指针,front指针指向队头元素,rear指针指向队尾元素的下一个位置,当front等于rear时,队列为空

但是这样又出现了新的问题:

  • 当队列进进出出数据后,front指针指向了队列后边的元素,而插入数据总是从队尾添加,这样会导致front指针前的空间空置着。

51_4.png

  • 当插入的数据大于了队列的MAXSIZE,rear指针再往后加,就会导致越界的错误,但实际上,队列的0,1位置还是空闲的。我们称这种现象为”假溢出”。

51_5.png

3.循环队列

解决假溢出的办法就是,当队列后边满了之后,将rear指针再从头开始头尾相接,这样的顺序存储结构的队列称为循环队列。

51_6.png

新的问题又出现了…

上边我们提到, 当front等于rear时,队列为空。 那么当队列满时,也是front等于rear,这要如何判断队列是空的还是满的?

  • 一:设置一个标志变量flag,当front==rear,且flag=0时,队列为空,当front==rear,flag=1时,队列为满。
  • 二:队列为空时,front==rear,当队列满时,保留一个空闲单元。即(rear+1)%MAXSIZE == front。需要用取模运算,因为不停rear加1可能会超过一圈。这里我们主要使用第二种方法来实现循环队列。

51_7.png

4.顺序存储结构实现循环队列

4、1 结构体

typedef struct {
    SElemType data[MAXSIZE];
    int front;      // 队列头
    int rear;       // 队列尾
}SqQueue;

4、2 初始化空队列

Status InitQueue(SqQueue *S){
    S->front = 0;
    S->rear = 0;
    return OK;
}

4、3 添加操作

Status EnterQueue(SqQueue *S,SElemType e){

    if (S == NULL) {
        return ERROR;
    }

    if ((S->rear+1)%MAXSIZE == S->front) {
        printf("队列已满\n");
        return ERROR;
    }

    S->data[S->rear] = e;
    S->rear = (S->rear+1)%MAXSIZE;  // 防止rear值大于一圈

    return OK;
}

4、4 删除操作

Status DeleteQueue(SqQueue *S,SElemType *e){
    if (S == NULL) {
        return ERROR;
    }

    if (S->front == S->rear) {
        printf("队列已空\n");
        return ERROR;
    }

    *e = S->data[S->front];
    S->front = (S->front+1)%MAXSIZE;
    return OK;
}

4、5 队列长度计算

  • 当rear>front时,队列的长度为rear-front;
  • 当rear<front时,队列的长度为MAXSIZE-front 与 rear的和。

51_8.png

通用的计算长度公式为:

(rear – front + MAXSIZE)%MAXSIZE

int GetQueueLength(SqQueue S){
    return (S.rear - S.front + MAXSIZE) % MAXSIZE;
}

4、6 判断是否为空

Status QueueEmpty(SqQueue S){
    if (S.front == S.rear) {
        return TRUE;
    }
    return FALSE;
}

4、7 遍历队列

Status QueueTraver(SqQueue S){

    int p = S.front;
    while (p+1 != S.rear+1) {
        printf("%d ",S.data[p]);
        p = (p+1)%MAXSIZE;
    }

    printf("\n");
    return OK;
}

文章永久链接:https://tech.souyunku.com/31426

未经允许不得转载:搜云库技术团队 » 顺序存储队列

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们