• 数据结构之队的实现


    𝙉𝙞𝙘𝙚!!👏🏻‧✧̣̥̇‧✦👏🏻‧✧̣̥̇‧✦ 👏🏻‧✧̣̥̇:Solitary-walk

          ⸝⋆   ━━━┓
         - 个性标签 - :来于“云”的“羽球人”。 Talk is cheap. Show me the code
    ┗━━━━━━━  ➴ ⷯ

    本人座右铭 :   欲达高峰,必忍其痛;欲戴王冠,必承其重。

    👑💎💎👑💎💎👑 
    💎💎💎自💎💎💎
    💎💎💎信💎💎💎
    👑💎💎 💎💎👑    希望在看完我的此篇博客后可以对你有帮助哟

    👑👑💎💎💎👑👑   此外,希望各位大佬们在看完后,可以互赞互关一下,看到必回
    👑👑👑💎👑👑👑     

    一·队的初始化

    二·队的销毁

    三·出队(头删)

    四·进队(尾插)

    五·队的判空

    六·取队头元素

    七·取队尾元素

    八·求队的大小

    九:循环队列的基本操作


     在进行以下接口的实现中,我们需要首先对队有一定的了解:

    1)队的特征:队头出元素,队尾进元素

    2)对于队我们又有顺序队和链队之分

    3)链队:它是由一个一个的结点进行连接起来的;其次每一个结点又有对应的数据域与指针域

                    所以说,我们的队其实是一个双层嵌套的结构体:一个是对队的自定义结构体(队头指                      针,队尾指针,size(注意他可以没有,但是为了避免多次的遍历,我们这里就设置了                    size:记录队的大小));另一个就是自定义的结点类型的结构体

    1.初始化

    这里只需把指向队的头指针,尾指针置空即可

    1. void QuequeInit(Queque* p)//对队进行初始化,所以这里传的是指向队的指针,(QNode* p)这样写是不对的
    2. {
    3. assert(p);
    4. p->phead = NULL;
    5. p->ptail = NULL;
    6. p->size = 0;
    7. }
    2.销毁

    其实同链表的销毁是一样的,我们只需把结点进行一个一个的free就行了

    还有就是销毁完之后别忘了让头尾指针置空

    3.出队

    出队首先是队头进行的

    这里我们就需要对元素个数进行判断:是只有一个元素还是多个元素

    元素出队之后别忘了size--

     

     当队里面只有一个元素的时候,把1 删除之后,这就是一个空队了,所以在出队之后就需要对头尾指针进行置空

     

     当我有多个数据时,就正常进行头删就行别忘了对应的头节点需要进行更新

    1. void QuequePop(Queque* p)//出队,在队头进行
    2. {
    3. //2种情况 只有1个结点 有多个结点
    4. assert(p);
    5. assert(!QuequeEmpty(p));//确保队不为空
    6. if (p->phead->next == NULL)
    7. {
    8. free(p->phead);
    9. p->phead =p->ptail = NULL;
    10. return;
    11. }
    12. else
    13. {
    14. QNode* next = p->phead->next;
    15. free(p->phead);
    16. p->phead = next;
    17. }
    18. //别忘size--
    19. p->size--;//注意--和-1区别
    20. }

    4.进队

    1)进队换言之就是尾插,首先我们需要对尾插进来的数据进行结点的创建

    2)判空 的操作:为空此时尾插进来 的数据就是我的新的头尾结点;不为空,尾插进来的数据就是新的尾结点,进行尾结点的更新

    1. void QuequePush(Queque* p,DataType x)//进队,在队尾进行
    2. {
    3. // 1 创建一个结点 2 对队进行判空操作
    4. assert(p);
    5. QNode* newnode = (QNode*)malloc(sizeof(QNode));//这里是对结点开辟空间,sizeof(Queque)这样写是错误的
    6. if (newnode == NULL)
    7. {
    8. perror("malloc fail\n");
    9. return;
    10. }
    11. //开辟成功
    12. newnode->data = x;
    13. newnode->next = NULL;
    14. //对队的判空操作
    15. if (p->phead == NULL)
    16. {
    17. assert(p->ptail == NULL);//确保尾指针也为空
    18. p->ptail = p->phead = newnode;
    19. }
    20. else
    21. {
    22. p->ptail->next = newnode;
    23. p->ptail = newnode;//尾结点更新
    24. }
    25. //别忘了size++
    26. p->size++;
    27. }

    5.判空
    1. bool QuequeEmpty(Queque* p)//判空
    2. {
    3. assert(p);
    4. return p->phead == NULL
    5. && p->ptail == NULL;
    6. //return p->size == 0;//注意这里一定要保持size一致性,即不要忘了++ / --
    7. }
    6.取队头元素
    1. DataType QuequeFront(Queque* p)//取队头元素
    2. {
    3. assert(p);
    4. assert(!QuequeEmpty(p));
    5. return p->phead->data;
    6. //取完队头元素不要忘了--
    7. }
    7.取队尾元素
    1. DataType QuequeBack(Queque* p)//取队尾元素
    2. {
    3. assert(p);
    4. assert(!QuequeEmpty(p));
    5. return p->ptail->data;
    6. }
    8.队的大小
    1. int QuequeSize(Queque* p)//队的大小
    2. {
    3. assert(p);
    4. return p->size;
    5. }

    Quqque.h对应完整代码:

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int DataType;
    7. //定义一个结构体:单链表可以解决没必要用双向链表,(单链表)链队列:数据域,指针域
    8. //注意以下2个结构体不能进行合并
    9. typedef struct QuequeNode
    10. {
    11. //注意以下只是定义队列的一个结点对应的类型
    12. DataType data;//数据域
    13. struct SLQuequeNode* next;//指针域
    14. }QNode;
    15. typedef struct Queque
    16. {
    17. //注意以下只是定义队列的类型
    18. QNode* phead;//队列的头指针
    19. QNode* ptail;//队列的尾指针
    20. int size;//记录数据个数,避免后续的遍历
    21. }Queque;
    22. //队列接口的实现
    23. void QuequeInit(Queque* p);//初始化
    24. void QuequeDestroy(Queque* p);//销毁
    25. void QuequePop(Queque* p);//出队,在队头进行
    26. void QuequePush(Queque* p,DataType x);//进队,在队尾进行
    27. bool QuequeEmpty(Queque* p);//判空
    28. DataType QuequeFront(Queque* p);//
    29. DataType QuequeBack(Queque* p);//
    30. int QuequeSize(Queque* p);//队的大小

    Quqque.c对应完整代码:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"Queque.h"
    3. void QuequeInit(Queque* p)//对队进行初始化,所以这里传的是指向队的指针,(QNode* p)这样写是不对的
    4. {
    5. assert(p);
    6. p->phead = NULL;
    7. p->ptail = NULL;
    8. p->size = 0;
    9. }
    10. void QuequeDestroy(Queque* p)//销毁
    11. {
    12. assert(p);
    13. /*Queque* pcur = p->phead;*///因为是对结点一个一个删除
    14. QNode* pcur = p->phead;
    15. while (pcur)
    16. {
    17. /*Queque* next = pcur->next;*///错误写法,原因同上
    18. QNode* next = pcur->next;
    19. free(pcur);
    20. pcur = next;
    21. }
    22. //别忘了执行以下操作
    23. p->phead = NULL;
    24. p->ptail = NULL;
    25. p->size = 0;
    26. }
    27. void QuequePop(Queque* p)//出队,在队头进行
    28. {
    29. //2种情况 只有1个结点 有多个结点
    30. assert(p);
    31. assert(!QuequeEmpty(p));//确保队不为空
    32. if (p->phead->next == NULL)
    33. {
    34. free(p->phead);
    35. p->phead =p->ptail = NULL;
    36. return;
    37. }
    38. else
    39. {
    40. QNode* next = p->phead->next;
    41. free(p->phead);
    42. p->phead = next;
    43. }
    44. //别忘size--
    45. p->size--;//注意--和-1区别
    46. }
    47. void QuequePush(Queque* p,DataType x)//进队,在队尾进行
    48. {
    49. // 1 创建一个结点 2 对队进行判空操作
    50. assert(p);
    51. QNode* newnode = (QNode*)malloc(sizeof(QNode));//这里是对结点开辟空间,sizeof(Queque)这样写是错误的
    52. if (newnode == NULL)
    53. {
    54. perror("malloc fail\n");
    55. return;
    56. }
    57. //开辟成功
    58. newnode->data = x;
    59. newnode->next = NULL;
    60. //对队的判空操作
    61. if (p->phead == NULL)
    62. {
    63. assert(p->ptail == NULL);//确保尾指针也为空
    64. p->ptail = p->phead = newnode;
    65. }
    66. else
    67. {
    68. p->ptail->next = newnode;
    69. p->ptail = newnode;//尾结点更新
    70. }
    71. //别忘了size++
    72. p->size++;
    73. }
    74. bool QuequeEmpty(Queque* p)//判空
    75. {
    76. assert(p);
    77. return p->phead == NULL
    78. && p->ptail == NULL;
    79. //return p->size == 0;//注意这里一定要保持size一致性,即不要忘了++ / --
    80. }
    81. DataType QuequeFront(Queque* p)//取队头元素
    82. {
    83. assert(p);
    84. assert(!QuequeEmpty(p));
    85. return p->phead->data;
    86. //取完队头元素不要忘了--
    87. }
    88. DataType QuequeBack(Queque* p)//取队尾元素
    89. {
    90. assert(p);
    91. assert(!QuequeEmpty(p));
    92. return p->ptail->data;
    93. }
    94. int QuequeSize(Queque* p)//队的大小
    95. {
    96. assert(p);
    97. return p->size;
    98. }

    test.c对应完整代码:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"Queque.h"
    3. void Quequetest()
    4. {
    5. Queque plist;
    6. QuequeInit(&plist);
    7. QuequePush(&plist, 1);
    8. QuequePush(&plist, 2);
    9. QuequePush(&plist, 3);
    10. QuequePush(&plist, 4);
    11. //QuequePop(&plist);
    12. //QuequePop(&plist);
    13. //QuequePop(&plist);
    14. //QuequePop(&plist);
    15. while (!QuequeEmpty(&plist))//打印队的数据,只要不为空即可
    16. {
    17. printf("%d ", QuequeFront(&plist));//其实就是取出队头元素
    18. QuequePop(&plist);//出队
    19. }
    20. printf("\n");
    21. QuequeDestroy(&plist);
    22. }
    23. int main()
    24. {
    25. Quequetest();
    26. return 0;
    27. }
    9.循环队列的基本操作

    对于循环队列,自然也是有2 中方式可以实现:数组 或者是 链表

    循环队列的有点就是避免了空间的浪费,可以重复使用

    9.1 前期知识的了解

    队最基本的性质:先进先出,队尾进入,队头出数据

    为例了方便出队,进队的操作,定义2个指针 rear(尾指针)front (头指针)

    数组实现如下:

    定义一个队的结构

    typedef struct Queue

    {

        DataType* a ;

       int  rear  ;

      int   front ;

    }Queue;

    9.2  循环队列的初始化

     问题就来了:rear 的初始值到底是  -1 还是 0 ?

    其实都可以,关键是看自己的需求:我以暂时以 rear = 0 他可以很直接的表明 队有效 的长度

     9.3 进队

    9.4 出队

    9.5 判空

    rear == front

    9.6  判满

    9.7 队头元素获取

    这个就很简单了,直接对 front这个下标位置进行访问即可

    9.8 队尾元素获取

    注意rear 是指向队尾元素的下一个位置,所以需要 访问的是 rear -1 这个下标位置的数据

     OK以上就是对循环队列的简单介绍

    下面小试牛刀一把吧

    9.9 设计循环队列

    题目:

    OJ代码:

    1. typedef struct {
    2. // 用数组方式实现循环队列
    3. int* a;
    4. int front;//队头指针
    5. int rear;//队尾指针
    6. int k;//队长,方便确定数组开多大空间
    7. } MyCircularQueue;
    8. bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    9. return obj->rear == obj->front;
    10. }
    11. bool myCircularQueueIsFull(MyCircularQueue* obj) {
    12. return obj->front == (obj->rear+1) %(obj->k+1);
    13. }
    14. MyCircularQueue* myCircularQueueCreate(int k) {
    15. MyCircularQueue*obj = ( MyCircularQueue*)malloc(sizeof( MyCircularQueue));
    16. obj->a = (int*)malloc(sizeof(int)*(k+1));//数组开辟空间
    17. obj->front = obj->rear = 0;
    18. obj->k = k;
    19. return obj;
    20. }
    21. bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    22. if( myCircularQueueIsFull(obj) == true)//判断是否满
    23. return false;
    24. //进队动rear指针
    25. obj->a[obj->rear] = value;
    26. obj->rear = (obj->rear+1)% (obj->k+1);//保证rear 指向队尾元素的下一个位置避免越界
    27. return true;
    28. }
    29. bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    30. if(myCircularQueueIsEmpty(obj) == true)//是否为空
    31. return false;
    32. obj->front = (obj->front+1)% (obj->k+1);//避免越界
    33. return true;
    34. }
    35. int myCircularQueueFront(MyCircularQueue* obj) {
    36. if(myCircularQueueIsEmpty(obj) == true)//是否为空
    37. return -1;
    38. return obj->a[obj->front];
    39. }
    40. int myCircularQueueRear(MyCircularQueue* obj) {
    41. if (myCircularQueueIsEmpty(obj) == true)//是否为空
    42. return -1;
    43. //return obj->a[obj->rear];//越界了,注意rear是指向队尾元素的下一个位置
    44. // if(obj->rear == 0)
    45. // return obj->a[obj->k];
    46. // else
    47. // return obj->a[obj->rear-1];
    48. return obj->a[((obj->rear - 1) + (obj->k + 1)) % (obj->k + 1)];
    49. }
    50. void myCircularQueueFree(MyCircularQueue* obj) {
    51. free(obj->a);
    52. free(obj);
    53. }
    结语:

    对于队列这种数据结构在我们的日常生活中还是随处可见的。餐厅的取号买饭,任务队列、事件队列、消息队列,和时间相关的东西都有队列的影响。所以说学好队列对生活的理解也会更深刻,以上就是我share 的内容,希望各位可以支持关注,谢谢大家!

  • 相关阅读:
    首次失败后,爱美客第二次冲刺港交所上市,财务负责人变动频繁
    unity中跟随鼠标浮动的面板,并可以自适应文字内容的大小
    C语言解题——指针解析(牛客网题目)
    25-什么是事件循环
    双十二有哪些实用性强的数码好物?值得入手的实用数码好物推荐
    【Java校招面试】实战面经(十)
    java基于springboot+vue驾校预约网站管理系统
    数据结构 冒泡排序 选择排序 学习笔记
    JAVA基础(JAVA SE)学习笔记(七)面向对象编程(进阶)
    Java 多线程(四):锁(二)
  • 原文地址:https://blog.csdn.net/X_do_myself/article/details/134220644