• 使用C语言实现链队(带头结点和不带头结点)


    目录

    1.链队

    2.链队的相关操作

    (1)数据结构的定义

    (2)初始化

    (3)判空和入队操作

    (4)出队操作

    (5)获取队头节点

    (6)主函数

    (7)测试


    1.链队

    使用链表表示的队列称为链队

    链队需要两个分别指向队头和队尾的指针(头指针和尾指针)才能唯一的确定。为了进行操作的方便我们可以为链队设置头指针,用于入队和出队操作。

    相对于顺序队列来说,链队的入队不需要考虑是否申请的空间是否会满的问题,而且在判断队列为的问题上也比较的方便,不需要太多的操作就可以判断,也不用太多的方法考虑。

    注:空的链队的头指针和尾指针都指向头节点。

    刚开始的时候头指针和尾指针指向的是同一个节点(头节点)。

    这是入队一些节点之后的情况,其实和单链表是差不多的,只是在删除和插入方面有限制。

    使用C语言实现单链表(带头结点)

    使用C语言实现单链表(不带头结点)

    使用C语言实现循环单链表(带头结点)

    2.链队的相关操作

    (1)数据结构的定义

    1. #include
    2. #include
    3. #define MAXSIZE 10
    4. typedef int ElemType;
    5. typedef struct LinkNode {
    6. ElemType data;
    7. struct LinkNode*next;
    8. }LinkNode;
    9. typedef struct{
    10. LinkNode*front,*rear;
    11. }LinkQueue;

    (2)初始化

    带头结点:

    1. //初始化
    2. void InitLinkQueue(LinkQueue&q){
    3. q.front=q.rear=(LinkNode*)malloc(sizeof(LinkNode));
    4. q.rear=q.front;
    5. q.rear->next=NULL;
    6. }
    7. //销毁链队
    8. void DestryLinkQueue(LinkQueue&q){
    9. while(q.front!=q.rear){
    10. LinkNode*p=q.front->next;
    11. if(q.front->next==q.rear){
    12. q.rear=q.front;
    13. }
    14. q.front->next=p->next;
    15. free(p);
    16. }
    17. free(q.front);
    18. free(q.rear);
    19. printf("销毁成功!\n");
    20. }
    21. void MenuSqQueue(){
    22. printf("--------------1.入队操作---------\n");
    23. printf("--------------2.出队操作---------\n");
    24. printf("--------------3.获取队头元素-----\n");
    25. printf("--------------4.重新初始化-------\n");
    26. printf("--------------5.退出操作---------\n");
    27. }

    不带头结点:

    1. //初始化
    2. void InitLinkQueue(LinkQueue&q){
    3. q.rear=q.front=NULL;
    4. }
    5. //销毁链队
    6. void DestryLinkQueue(LinkQueue&q){
    7. while(q.front!=NULL){
    8. LinkNode*p=q.front;
    9. if(q.front==q.rear&&q.front!=NULL){
    10. q.rear=q.front;
    11. }
    12. q.front=p->next;
    13. free(p);
    14. }
    15. printf("销毁成功!\n");
    16. }

    注:注意不带头结点和带头结点的销毁操作处理。

    (3)判空和入队操作

    带头结点:

    1. //判空
    2. bool isEmpty(LinkQueue&q){
    3. if(q.front==q.rear){
    4. return true;
    5. }else{
    6. return false;
    7. }
    8. }
    9. //入队操作
    10. void EnQueue(LinkQueue&q,ElemType e){
    11. LinkNode*s=(LinkNode*)malloc(sizeof(LinkNode));
    12. s->data=e;
    13. s->next=q.rear->next;
    14. q.rear->next=s;
    15. q.rear=s;
    16. printf("入队成功!\n");
    17. }

    不带头结点:

    1. //入队操作
    2. void EnQueue(LinkQueue&q,ElemType e){
    3. LinkNode*s=(LinkNode*)malloc(sizeof(LinkNode));
    4. s->data=e;
    5. s->next=NULL;
    6. if(q.front==NULL){
    7. q.front=s;
    8. q.rear=s;
    9. }else{
    10. q.rear->next=s;
    11. q.rear=s;
    12. }
    13. printf("入队成功!\n");
    14. }

    注:当队列中没有节点的时候,需要进行特殊的处理。

    (4)出队操作

    带头结点:

    1. //出队操作
    2. void DeQueue(LinkQueue&q,ElemType &e,int&mask){
    3. if(isEmpty(q)){
    4. printf("队列为空!\n");
    5. mask=0;
    6. return;
    7. }
    8. LinkNode*p=q.front->next;
    9. e=p->data;
    10. mask=1;
    11. //如果是最后一个节点需要特殊处理
    12. if(q.front->next==q.rear){
    13. q.rear=q.front;
    14. }
    15. q.front->next=p->next;
    16. free(p);
    17. printf("出队成功!\n");
    18. }

    注:虽然设置了头结点,但是也需要对其最后一个节点进行特殊的处理。

    不带头结点:

    1. //出队
    2. void DeQueue(LinkQueue&q,ElemType&e,int&mask){
    3. if(q.front==NULL){
    4. printf("空队列!\n");
    5. mask=0;
    6. return;
    7. }
    8. LinkNode*p=q.front;
    9. e=p->data;
    10. mask=1;
    11. q.front=p->next;
    12. if(q.rear==p){
    13. q.rear=NULL;
    14. q.front=NULL;
    15. }
    16. free(p);
    17. printf("出队成功!\n");
    18. }

    注:对于不带头结点的出队操作主要注意的是只有一个节点的时候,那么需要对其进行特殊的处理。

    (5)获取队头节点

    带头结点:

    1. //获取队头元素
    2. void GetQueueHead(LinkQueue&q,ElemType &e,int&mask){
    3. if(isEmpty(q)){
    4. printf("队列为空!\n");
    5. mask=0;
    6. return;
    7. }
    8. e=q.front->next->data;
    9. mask=1;
    10. }

    不带头结点:

    1. //获取队头元素
    2. void GetQueueHead(LinkQueue&q,ElemType &e,int&mask){
    3. if(q.front==NULL){
    4. printf("队列为空!\n");
    5. mask=0;
    6. return;
    7. }
    8. e=q.front->data;
    9. mask=1;
    10. }

    (6)主函数

    1. int main(){
    2. LinkQueue q;
    3. ElemType e;
    4. int flag=0;
    5. InitLinkQueue(q);
    6. int mask=1;
    7. while(1){
    8. MenuSqQueue();
    9. printf("请输入操作: ");
    10. scanf("%d",&flag);
    11. switch(flag){
    12. case 1:
    13. printf("请输入元素(-1_end): ");
    14. scanf("%d",&e);
    15. while(e!=-1){
    16. EnQueue(q,e);
    17. printf("请输入元素(-1_end): ");
    18. scanf("%d",&e);
    19. }
    20. break;
    21. case 2:
    22. DeQueue(q,e,mask);
    23. if(mask!=0){
    24. printf("出队元素 = %d\n",e);
    25. }
    26. break;
    27. case 3:
    28. GetQueueHead(q,e,mask);
    29. if(mask!=0){
    30. printf("获取元素 = %d\n",e);
    31. }
    32. break;
    33. case 4:
    34. InitLinkQueue(q);
    35. printf("初始化成功!\n");
    36. break;
    37. default:
    38. DestryLinkQueue(q);
    39. printf("操作结束!\n");
    40. }
    41. if(flag==5){
    42. break;
    43. }
    44. }
    45. return 0;
    46. }

    (7)测试

  • 相关阅读:
    【36C++STL-常用容器----3、stack容器详解】
    【数据结构初阶】链式二叉树接口实现+痛苦的OJ题
    【C++】走进 ⌈ 类和对象 ⌋ 的核心 - 感受C++的精华 _ 剖析默认成员函数 | 构造函数 | 析构函数 | 拷贝构造函数 | 赋值运算符重载
    递归神经网络 (RNN)
    【ubuntu22.04 文件管理器nautilus配置默认终端为alacritty】
    力扣刷题学习SQL篇——1-17 查询近30天活跃用户数(日期进行区间判定)
    前端JavaScript中的 == 和 ===区别,以及他们的应用场景,快来看看吧,积累一点知识。
    [云原生] k8s之存储卷
    对于Mac OS10.1x合适安装的Typora版本合集
    示波器探头对测量电容负荷有影响吗?
  • 原文地址:https://blog.csdn.net/Keep_Trying_Go/article/details/126321497