LeetCode题解|622.设计循环队列

题目描述及链接

设计循环队列
LeetCode题解|622.设计循环队列_第1张图片

题解

本题可以用数组实现,也可以用链表实现。
这里使用数组(动态数组)实现。

先定义结构

typedef struct {
    int* a;
    int front;
    int tail;
    int k;
} MyCircularQueue;

a表示表示动态数组,front指向队列第一个元素,tail指向队列最后一个元素,k表示队列可用长度。

接下来初始化队列
初试时,应该使用malloc开辟一个MyCircularQueue结构体,并给这个结构体中的a开辟k+1个元素(多一个用于判断队列是否为满),并将front和tail均置为0,每次入队一个元素,tail++。这样,tail总是指向下一个可用位置。

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* cq = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    cq->a = malloc(sizeof(int)*(k+1));
    cq->front = cq->tail = 0;
    cq->k = k;

    return cq;
}

因为实现入队列时需要判断队列是否为满、出队列时需要判断队列是否为空,所以我们先实现判满和判空函数.

判空只要看front是否于tail相等即可

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->front == obj->tail;
}

判满只有两种情况,即front在tail之前和front在tail之后
LeetCode题解|622.设计循环队列_第2张图片

LeetCode题解|622.设计循环队列_第3张图片

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return (obj->tail+1) % (obj->k+1) == obj->front;
}

接下来实现入队函数

循环队列的要点就是如何实现当tail指向数组最后一个元素时,再入队一个元素后如何使tail又指向第一个元素。
LeetCode题解|622.设计循环队列_第4张图片

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if(myCircularQueueIsFull(obj))
        return false;
    obj->a[obj->tail] = value;
    ++obj->tail;
    obj->tail %= (obj->k+1);

    return true;
}

LeetCode题解|622.设计循环队列_第5张图片

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return false;

    ++obj->front;
    obj->front %= (obj->k+1);
    return true;

}

返回队首元素

int myCircularQueueFront(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;
    return obj->a[obj->front];
}

返回队尾元素,可以计算下标,也可以用条件语句
LeetCode题解|622.设计循环队列_第6张图片

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
        return -1;

    // if(obj->tail == 0)
    //     return obj->a[obj->k];
    // else
    //     return obj->a[obj->tail-1];

    //或者计算下标
    int i = (obj->tail+obj->k) % (obj->k+1);
    return obj->a[i];
}

最后释放空间的时候,注意有两层结构,要先释放内层空间。

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    free(obj);
}

LeetCode题解|622.设计循环队列_第7张图片

LeetCode题解|622.设计循环队列_第8张图片

总结

一般队列元素都是malloc出来的,每次出队都会free,即使不用循环队列也不会造成空间浪费。

循环队列的大小是固定的。

本题主要提供了一种新的思路。

循环队列在操作系统生产者消费者模型中有使用。

你可能感兴趣的:(LeetCode,leetcode,算法)