力扣622,设计循环队列

文章目录

    • 题目描述
    • 题目分析
    • 使用数组的方式来解题
    • 使用链表的方式

题目描述

设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。

链接:https://leetcode-cn.com/problems/design-circular-queue

题目分析

这里稍微有点复杂的就是判空和判满的操作,所以要多一个空间(可以多画图理解)
力扣622,设计循环队列_第1张图片

使用数组的方式来解题

删除的时候head向前走就行,插入的时候在tail的位置
然后那个多出来的为空的是动态的,是不断在发生变化的
力扣622,设计循环队列_第2张图片

typedef struct
{
    int *a;   
    int head;
    int tail;
    int k;    //可以存放元素的个数
} MyCircularQueue;

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

MyCircularQueue* myCircularQueueCreate(int k) 
{
    MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    assert(obj);

    obj->a=(int*)malloc(sizeof(int)*(k+1)); //多开一个空间哦
    obj->head=obj->tail=0;
    obj->k=k;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    assert(obj);
    if(myCircularQueueIsFull(obj))  //满了就报错了
    return false;
    
    obj->a[obj->tail]=value;
    if(obj->tail==obj->k)  //如果tail在最后一个位置就要重新回到0的位置
    {
      obj->tail=0;
    }
    else
    {
        obj->tail++;
    }
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) 
{
    assert(obj);
    if(myCircularQueueIsEmpty(obj)) //为空就不用删除了
    return false;  

    if(obj->head==obj->k)
    {
        obj->head=0;
    }
    else
    {
       obj->head++;
    }
     return true;
}

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

    return obj->a[obj->head];  //头肯定就是head所在的下标
}

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

    //队尾元素,是tail的前一个,但是tail为0的时候就是下标为k
    if(obj->tail==0)
    {
        return obj->a[obj->k];
    }
    else
    {
        return obj->a[obj->tail-1];
    }
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj)
{
    assert(obj);
    //head和tail指向同一个位置的时候才是空
    return obj->head==obj->tail; 

}

bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    //判满有两种情况 1,tail在下标为k的位置,head在0
    //2tail的前一个位置是head
    if((obj->tail==obj->k) && (obj->head==0))
    {
        return true;
    }
    if(obj->tail+1==obj->head)
    {
        return true;
    }
    return false;
}

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

使用链表的方式

使用链表的方式有点难的地方主要还是去构造一个循环的单链表
但是我觉得还是以链表的方式构造简单一些
力扣622,设计循环队列_第3张图片

typedef struct QNode
{
    int data;
    struct QNode* next;
}QNode;

typedef struct 
{
  QNode* head;
  QNode* tail;
} MyCircularQueue;

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

MyCircularQueue* myCircularQueueCreate(int k)
{
    MyCircularQueue* obj =(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->tail=obj->head=NULL;
    k=k+1;  //多开辟一个空间哦
    while(k)           //搞一个循环的单链表出来
    {
        QNode* node=(QNode*)malloc(sizeof(QNode));
        if(obj->tail==NULL && obj->head==NULL)
        {
            obj->tail=obj->head=node;
        }
        else
        {
            obj->tail->next=node;
            obj->tail=node;
        }
        k--;
    }
    obj->tail->next=obj->head;
    obj->tail=obj->head;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value)
{
    if(myCircularQueueIsFull(obj)) //满了就报错
    return false;
    
    obj->tail->data=value;
    obj->tail=obj->tail->next;
    return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj)
{
    if(myCircularQueueIsEmpty(obj))  //为空就报错
    return false;

    obj->head=obj->head->next;
    return true;
}

int myCircularQueueFront(MyCircularQueue* obj)
{
    if(myCircularQueueIsEmpty(obj))
    return -1;
 
    return obj->head->data;
}

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

    //是tail的前一个节点哦
    QNode* cur=obj->head;
    while(cur->next!=obj->tail)
    {
        cur=cur->next;
    }
    return cur->data;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) 
{
    return obj->tail==obj->head;   //tail和head相等就是空
}

bool myCircularQueueIsFull(MyCircularQueue* obj)
{
    return obj->tail->next==obj->head;  //tail的下一个节点是head就是空
}

void myCircularQueueFree(MyCircularQueue* obj) 
{
    QNode* cur=obj->head;
    while(cur->next!=obj->head)
    {
        QNode* save=cur->next;
        free(cur);
        cur=save;
    }
    free(cur);
    free(obj);
}

你可能感兴趣的:(c语言,链表,数据结构)