循环队列(Circular_Queue)(C语言)

目录

一、循环队列介绍

1、题目描述

2、思路

1.顺序结构

​编辑

2.链式结构

二、顺序结构代码实现

1.设计结构体

2.判断队列是否为空

3.判断队列是否为满

4.创建循环队列

5.入队

6.出队

7.返回队头数据

8.返回队尾数据

9.销毁队列

三、链式结构代码实现

1.设计结构体

2.判断队列是否为空

3.判断队列是否为满

4.创建循环队列

5.入队

6.出队

7.返回队头数据

8.返回队尾数据

9.销毁队列

四、总结


一、循环队列介绍

1、题目描述

622. 设计循环队列 - 力扣(LeetCode)

2、思路

循环队列遵循队列的特征尾进头出(FIFO),所以在设计的时候我们需要保证像队列(Queue)的实现一样,包含头尾指针。

那么问题来了,我们应该选择什么样的存储结构解决这个问题呢?(顺序/链式)

ok,我们两个都要。

1.顺序结构

数组是线性的,遵循尾进头出的原则

1.我们需要在头指针元素销毁后,向后移动头指针。

2.我们需要在插入新元素时,向后移动尾指针。

3.当尾指针到达数组底部后,将其调至头指针之前的空位。

4.特别注意,为了判断队列的满/空,我们需要在队列可存储大小k之上再加一个位置,用来判断队列的满/空,front==rear(empty),rear+1=front(full)

2.链式结构

其实更好理解,相当于不断创建一个长度小于等于k的单链表。单链表会像火车一样不断往后开。

每当创建新节点,创建tail->next节点,tail往后移动。

每当删除节点,删除head指向节点,head也往后移动。

可以完全还原循环链表的功能。

但我觉得这样做是不是有点无聊。。。

二、顺序结构代码实现

1.设计结构体

数组 头尾指针 数组真实记录数据长度为k,而我们需要创造的长度为k+1,留一个空位用来进行前文提及的判断空/满。

要注意的是,front&back的数值可能会超过数组容量大小,这是因为front&back只是两个整数,用来记录头尾坐标的,在真正实现中会将其取模以达到循环的效果,大家看起来好像是数组扩张了。

typedef struct {
    int* a;
    int front;
    int back;
    int k;//用来记录队列长度
} MyCircularQueue;

2.判断队列是否为空

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

3.判断队列是否为满

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

4.创建循环队列

注意这里的malloc创建了k+1个空间

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

5.入队

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

6.出队

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

7.返回队头数据

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

8.返回队尾数据

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

9.销毁队列

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

三、链式结构代码实现

1.设计结构体

创建头尾节点,容量,节点个数。

typedef struct {
    struct ListNode* head;
    struct ListNode* tail;
    int capacity;
    int size;
} MyCircularQueue;

2.判断队列是否为空

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    return obj->size == 0;
}

3.判断队列是否为满

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    return obj->size == obj->capacity;
}

4.创建循环队列

MyCircularQueue* myCircularQueueCreate(int k) {
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    obj->capacity = k;
    obj->size = 0;
    obj->head = obj->tail = NULL;
    return obj;
}

5.入队

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (obj->size >= obj->capacity) {
        return false;
    }
    struct ListNode* node = (struct ListNode*)malloc(sizeof(struct ListNode));
    node->val = value;
    node->next = NULL;
    if (!obj->head) {
        obj->head = obj->tail = node;
    }
    else {
        obj->tail->next = node;
        obj->tail = node;
    }
    obj->size++;
    return true;
}

6.出队

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (obj->size == 0) {
        return false;
    }
    struct ListNode* node = obj->head;
    obj->head = obj->head->next;
    obj->size--;
    free(node);
    return true;
}

7.返回队头数据

int myCircularQueueFront(MyCircularQueue* obj) {
    if (obj->size == 0) {
        return -1;
    }
    return obj->head->val;
}

8.返回队尾数据

int myCircularQueueRear(MyCircularQueue* obj) {
    if (obj->size == 0) {
        return -1;
    }
    return obj->tail->val;
}

9.销毁队列

void myCircularQueueFree(MyCircularQueue* obj) {
    for (struct ListNode* curr = obj->head; curr;) {
        struct ListNode* node = curr;
        curr = curr->next;
        free(node);
    }
    free(obj);
}

四、总结

其实两种结构的实现,均不是循环结构,都是线性结构,不由得感叹人类的智慧是无穷的,这也告诉我们做题不要那么死板,有时候奇怪的思路胜过暴力的解法。一起加油,各位。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值