设计循环队列@Leetcode —— 栈和队列

另外扩展一下,实际中我们有时还会使用一种队列叫循环队列。它可以重复利用之前的空间。如操作系统课程讲解生产者消费者模型时就会使用循环队列。环形队列可以用数组实现,也可以用循环链表实现。多数都是用循环链表实现的。本文嘞,两个都实现一下吧!

正文开始@边通书

1. 题目

题目链接:设计循环队列
在这里插入图片描述
注意:
在这里插入图片描述
无论是数组实现还是链表实现,都要多开一个空间,否则无法区分判空判满。即要存k个数据的循环队列,要开(k+1)个空间。

写的过程也是出现了各种各样的小问题,它们都化作小注意写在文章中了。

2. 用循环链表实现循环队列

2.1 思路

思路无非是实现题目要求,做过队列基本操作,以及昨天的栈和队列相互实现,就应该清晰很多。
💙1. 入数据。同时也要注意,取队尾数据是tail的上一个节点中val
在这里插入图片描述
💙2. 出数据,front向后挪一个位置即可。
在这里插入图片描述
💙3. 判空判满的条件,画图(上图)即可知

注意
💛1.create时,弄清你要申请的空间,头脑中有类似下面的图。昨天做了栈和队列的相互实现,这个就是一样的。
在这里插入图片描述
💛2.遇到这样的报错,其实是因为前面的函数调用了后面的函数接口,那在前面声明一下就好了。
在这里插入图片描述

2.2 题解

typedef struct CircularListNode{
    int val;
    struct CircularListNode* next;
} CircularListNode;

typedef struct {
    CircularListNode* front;
    CircularListNode* tail;
    //int k; //不写这个也完全可以
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* q = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    q->front = q->tail = (CircularListNode*)malloc(sizeof(CircularListNode));
    //q->k = k;
    CircularListNode* cur = q->front;
    while(k--)
    {
        CircularListNode* newnode = (CircularListNode*)malloc(sizeof(CircularListNode));
        cur->next = newnode;
        cur = newnode;
    }
    cur->next = q->front;//尾链上头
    return q;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    assert(obj);
    if(myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        obj->tail->val = value;
        obj->tail = obj->tail->next;
        return true;
    }
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    assert(obj);
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        obj->front = obj->front->next;
        return true;
    }
}

int myCircularQueueFront(MyCircularQueue* obj) {
    assert(obj);
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        return obj->front->val;
    }
}

int myCircularQueueRear(MyCircularQueue* obj) {
    assert(obj);
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
        //找tail的上一个节点
        CircularListNode* prev = obj->front;
        while(prev->next != obj->tail)
        {
            prev = prev->next;
        }
        return prev->val;
    }
    
}

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

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    assert(obj);
    return obj->tail->next == obj->front;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    assert(obj);
    CircularListNode* cur = obj->front;
    while(cur->next != obj->front)
    {
        CircularListNode* next = cur->next;
        free(cur);
        cur = next;
    }
    free(cur);
    free(obj);
}


/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/

3. 用数组实现循环队列

3.1 思路

这个难点在于控制下标,但其实只需要把握好两个地方,画两个图就出来了 ——
💛1. 入队出队自己画图。
💛2. 保证fronttail下标实时有效。每次++,下一次都可能越界,就%= k+1处理一下。下图解释为什么是k+1
在这里插入图片描述

💛3. 取队尾元素,是取tail前一个元素。注意tail为0时,直接跳后面取
在这里插入图片描述
💛4. 如何判满?下面两幅图都是满的情况,找关系吧!
在这里插入图片描述

(tail+1)%(k+1) == front

3.2 题解

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


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

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);

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

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        obj->front++;
        obj->front %= obj->k+1;
        return true;
    }
}

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

int myCircularQueueRear(MyCircularQueue* obj) {
    if(myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else
    {
       if(obj->tail == 0)
           return obj->a[obj->k];
       else
           return obj->a[obj->tail-1];
    }
}

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

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

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->a);
    obj->front = obj->tail = 0;
    free(obj);
}

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/
  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮光 掠影

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值