• leetcode622.设计循环队列(C语言)


    622.设计循环队列
    622.设计循环队列

    目录

    一、题目链接和介绍

    二、大体思路

    三、具体步骤

    四、代码部分

    一、题目链接和介绍

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

    实现一个循环的队列,其特性队列的先进先出(FIFO)原则,队尾被连接在队首之后以形成一个循环,该题目即为实现其功能。

    二、大体思路

    ①创建一个大小为k+1的数组。使用headtail两个变量来记录数组中数据的变化;

    ②存入数据时,tail指针向后移动;删除数据时,head指针向前移动。

    ③因为要存放k个数据,我们开辟k+1的空间的目的就是防止存入数据时发生了覆盖,当tail+1==head时即表示队列存满。

    三、具体步骤

    3.1 创建结构体

    有一个head变量表示队列的头,tail表示队列的尾,k表示存入队列的大小,a开辟的数组。

    1. typedef struct {
    2. int *a;
    3. int k;
    4. int head;
    5. int tail;
    6. } MyCircularQueue;

    3.2 队列的创建

    因为结构体不好控制,而且下面题目的函数形参都是以结构体指针的形式传入,所以我们要初始创建时要使用结构体变量obj来控制。

    又因为函数作用域的原因,所以我们创建该结构体时要使用malloc来开辟,这样函数销毁的时候我们创建的变量才不会被销毁,并且可以成功返回该结构体指针。

    1. MyCircularQueue* myCircularQueueCreate(int k) {
    2. //控制该结构体(MyCircularQueue)的指针
    3. MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    4. //开辟k+1的数组空间
    5. obj->a=(int*)malloc(sizeof(int)*(k+1));
    6. obj->head=0;
    7. obj->tail=0;
    8. obj->k=k;
    9. return obj;
    10. }

    3.3 队列的插入

    我们的思路是,将数据插入到 a[tail] 的位置,然后使 tail++ ,这样就可以数据插入到队列中去。

    这里有一个问题,因为我们是循环队列,如果出现这种情况:

    head因为删除数据导致前移,然后插入数据时tail走出了数组。

     所以这时我们要判断,如果当tail==k+1时,我们就要让tail回归到对头。

    1. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    2. //如果队列未满,直接返回false,插入失败
    3. if(myCircularQueueIsFull(obj))
    4. return false;
    5. obj->a[obj->tail]=value;
    6. obj->tail++;
    7. //obj->tail%=(k+1)
    8. if (obj->tail==obj->k+1)
    9. {
    10. obj->tail=0;
    11. }
    12. return true;
    13. }

    3.4删除数据

    想删除数据,只用将head向前移动一格即可。当然,也可能出现以下这种情况。

    所以我们同样可以判断,当head==k+1时,我们将head移动到对头。

    1. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    2. if (myCircularQueueIsEmpty(obj))
    3. return false;
    4. ++obj->head;
    5. if (obj->head==obj->k+1)
    6. {
    7. obj->head=0;
    8. }
    9. return true;
    10. }

    3.5 队列的判空

    我们的思路是,队列初始状态下head和tail都存的是同一个下标,即head==tail==0,且我们规定了tail+1==head才是存满的,所以说只有当head和tail相等时队列才为空

    1. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    2. return obj->head==obj->tail;
    3. }

    3.6 队列的判满

    以下我们有两种形式判定队列的为满的情况

     

    二:我们先来看第种情况,设置一个临时变量temp为tail+1,如果tamp==head就表示队列当前为满返回true。

    种情况,设置一个临时变量temp为tail+1,如果temp==k+1,将temp置为0,再判断tamp是否等于head,如果等于,就表示为满,返回true

     

    1. bool myCircularQueueIsFull(MyCircularQueue* obj) {
    2. int next=obj->tail+1;
    3. //实际是再判断tail是否位于数组最后。
    4. if (next==obj->k+1)
    5. next=0;
    6. return next==obj->head;
    7. }

    3.7 队列头部数据

    这就很简单了,直接返回head下标处的数据即可。

    1. int myCircularQueueFront(MyCircularQueue* obj) {
    2. if (myCircularQueueIsEmpty(obj))
    3. return -1;
    4. else
    5. return obj->a[obj->head];
    6. }

    3.8 队列尾部数据

    这里又分两种情况:①tail未被置0 ②tail被置零。

    如果tail被置零,因为在程序的开始,我们就判断了队列是否为空,所以k位置处肯定是有数据的,我们直接返回k下标处的数据即可。

     

     

    1. int myCircularQueueRear(MyCircularQueue* obj) {
    2. if (myCircularQueueIsEmpty(obj))
    3. return -1;
    4. if (obj->tail==0)
    5. {
    6. return obj->a[obj->k];
    7. }
    8. //return obj->a[(obj->tail+k)%(k+1)]
    9. return obj->a[obj->tail-1];
    10. }

    3.9 队列的销毁

    我们首先要释放数组a,再释放队列。

    1. void myCircularQueueFree(MyCircularQueue* obj) {
    2. free(obj->a);
    3. free(obj);
    4. }

    四、代码部分

    1. //使用数组实现
    2. typedef struct {
    3. int *a;
    4. int k;
    5. int head;
    6. int tail;
    7. } MyCircularQueue;
    8. MyCircularQueue* myCircularQueueCreate(int k) {
    9. MyCircularQueue* obj=(MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    10. //开辟k+1的空间
    11. obj->a=(int*)malloc(sizeof(int)*(k+1));
    12. obj->head=0;
    13. obj->tail=0;
    14. obj->k=k;
    15. return obj;
    16. }
    17. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    18. return obj->head==obj->tail;
    19. }
    20. bool myCircularQueueIsFull(MyCircularQueue* obj) {
    21. int next=obj->tail+1;
    22. if (next==obj->k+1)
    23. next=0;
    24. return next==obj->head;
    25. }
    26. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    27. if(myCircularQueueIsFull(obj))
    28. return false;
    29. obj->a[obj->tail]=value;
    30. obj->tail++;
    31. //obj->tail%=(k+1)
    32. if (obj->tail==obj->k+1)
    33. {
    34. obj->tail=0;
    35. }
    36. return true;
    37. }
    38. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    39. if (myCircularQueueIsEmpty(obj))
    40. return false;
    41. ++obj->head;
    42. if (obj->head==obj->k+1)
    43. {
    44. obj->head=0;
    45. }
    46. return true;
    47. }
    48. int myCircularQueueFront(MyCircularQueue* obj) {
    49. if (myCircularQueueIsEmpty(obj))
    50. return -1;
    51. else
    52. return obj->a[obj->head];
    53. }
    54. int myCircularQueueRear(MyCircularQueue* obj) {
    55. if (myCircularQueueIsEmpty(obj))
    56. return -1;
    57. if (obj->tail==0)
    58. {
    59. return obj->a[obj->k];
    60. }
    61. //return obj->a[(obj->tail+k)%(k+1)]
    62. return obj->a[obj->tail-1];
    63. }
    64. void myCircularQueueFree(MyCircularQueue* obj) {
    65. free(obj->a);
    66. free(obj);
    67. }
  • 相关阅读:
    外包干了2个月,技术退步明显...
    软件测试面试题-一个前后端都能修改的bug,应该由谁修改?
    【负载均衡在线OJ项目日记】项目简介
    为什么要停止在 SpringBoot 中使用字段注,改用构造器注入
    Java:Exceptions相关学习
    如何将镜像烧写至iNand(fastboot命令的源码分析)
    Kotlin委托属性(1)
    力扣146|LRU缓存淘汰算法
    visual studio 启用DPI识别功能
    ES相关问题
  • 原文地址:https://blog.csdn.net/Brant_zero/article/details/125538360