C语言详解链式队列与循环队列的实现

C语言详解链式队列与循环队列的实现

链式队列的实现

链式队列是一种使用链表实现的队列。这种队列没有静态数组的限制,可以动态地添加或删除元素。

链式队列的定义

链式队列可以通过定义一个结构体来表示:

typedef struct node{
    int data;                   // 存放队列元素的数据
    struct node *next;          // 存放下一个元素的地址
}Node;                          // 队列元素的类型

typedef struct linked_queue{
    Node *front;                // 队头指针
    Node *rear;                 // 队尾指针
}LinkedQueue;                    // 队列类型

队列的初始化实现如下:

void InitQueue(LinkedQueue *q){
    q->front = q->rear = (Node*)malloc(sizeof(Node));
    q->front->next = NULL;
}

入队操作

当队列为空时,要插入的元素既是队头又是队尾。其他情况下,只需在队尾插入元素即可。

void EnQueue(LinkedQueue *q, int x){
    Node *p = (Node*)malloc(sizeof(Node));
    p->data = x;
    p->next = NULL;
    q->rear->next = p;
    q->rear = p;
}

出队操作

当队列为空时,无法进行出队操作。

int DeQueue(LinkedQueue *q){
    if(q->front == q->rear)  return -1; // 队列为空
    Node *p = q->front->next;
    int x = p->data;
    q->front->next = p->next;
    if(q->rear == p)    q->rear = q->front;
    free(p);
    return x;
}

循环队列的实现

循环队列可以使用静态数组来实现,是一种较为常用的队列实现方式。队列的头尾相连成一个环,可以循环利用数组空间,提高队列的利用率。

循环队列的定义

循环队列也可以通过定义一个结构体来表示:

typedef struct circular_queue{
    int *data;      // 存放队列元素的数组
    int front;      // 队头指针
    int rear;       // 队尾指针
    int size;       // 队列容量
}CircularQueue;     // 队列类型

队列的初始化实现如下:

void InitQueue(CircularQueue *q, int size){
    q->data = (int*)malloc(size * sizeof(int));
    q->front = q->rear = 0;
    q->size = size;
}

入队操作

当队列为空时,无论第一个插入的元素是哪个,队头与队尾都指向该元素。在队列不满的情况下,队尾指针右移,将新元素插入当前队尾的下一个位置。

bool EnQueue(CircularQueue *q, int x){
    if((q->rear + 1) % q->size == q->front)   return false; // 队列满
    q->data[q->rear] = x;
    q->rear = (q->rear + 1) % q->size;
    return true;
}

出队操作

当队列为空时,无法进行出队操作。在队列不空的情况下,队头指针右移,返回当前队头元素。

bool DeQueue(CircularQueue *q, int *x){
    if(q->front == q->rear)   return false; // 队列空
    *x = q->data[q->front];
    q->front = (q->front + 1) % q->size;
    return true;
}

示例说明

链式队列示例

下面是一个使用链式队列计算阶乘的示例:

#include <stdio.h>
#include <stdlib.h>

typedef struct node{
    int data;
    struct node *next;
}Node;

typedef struct linked_queue{
    Node *front;
    Node *rear;
}LinkedQueue;

void InitQueue(LinkedQueue *q){
    q->front = q->rear = (Node*)malloc(sizeof(Node));
    q->front->next = NULL;
}

void EnQueue(LinkedQueue *q, int x){
    Node *p = (Node*)malloc(sizeof(Node));
    p->data = x;
    p->next = NULL;
    q->rear->next = p;
    q->rear = p;
}

int DeQueue(LinkedQueue *q){
    if(q->front == q->rear)  return -1;
    Node *p = q->front->next;
    int x = p->data;
    q->front->next = p->next;
    if(q->rear == p)    q->rear = q->front;
    free(p);
    return x;
}

int Fac(int n){
    LinkedQueue q;
    InitQueue(&q);                  // 定义链式队列
    EnQueue(&q, 1);                 // 先将1入队
    int f = 1;
    while(n--){
        int x = DeQueue(&q);        // 出队
        f *= x;                     // 阶乘
        EnQueue(&q, x+1);           // 入队
    }
    return f;
}

int main(){
    int n = 5;
    int f = Fac(n);
    printf("The factorial of %d is %d.\n", n, f);
    return 0;
}

循环队列示例

下面是一个使用循环队列实现的简易银行大厅管理程序:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

typedef struct circular_queue{
    int *data;
    int front;
    int rear;
    int size;
}CircularQueue;

void InitQueue(CircularQueue *q, int size){
    q->data = (int*)malloc(size * sizeof(int));
    q->front = q->rear = 0;
    q->size = size;
}

bool EnQueue(CircularQueue *q, int x){
    if((q->rear + 1) % q->size == q->front)   return false;
    q->data[q->rear] = x;
    q->rear = (q->rear + 1) % q->size;
    return true;
}

bool DeQueue(CircularQueue *q, int *x){
    if(q->front == q->rear)   return false;
    *x = q->data[q->front];
    q->front = (q->front + 1) % q->size;
    return true;
}

int main(){
    CircularQueue q;
    int size = 5;
    InitQueue(&q, size);                // 初始化队列
    EnQueue(&q, 1);                     
    EnQueue(&q, 2);
    EnQueue(&q, 3);
    int x;
    DeQueue(&q, &x);                    // 办理业务1
    printf("办理业务1的顾客号码:%d\n", x);
    EnQueue(&q, 4);
    EnQueue(&q, 5);
    DeQueue(&q, &x);                    // 办理业务2
    printf("办理业务2的顾客号码:%d\n", x);
    EnQueue(&q, 6);
    EnQueue(&q, 7);
    while(DeQueue(&q, &x)){             // 查看当前队列中的客户
        printf("%d ", x);
    }
    printf("\n");
    return 0;
}

以上两个示例分别为链式队列和循环队列的应用,可以看到这两种队列的实现方式、操作和应用场景的不同,需要根据实际情况选择合适的队列实现方式。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言详解链式队列与循环队列的实现 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • vue中接口域名配置为全局变量的实现方法

    Vue中接口域名配置为全局变量的实现方法 在Vue项目中,我们通常需要配置接口的域名,以便在不同环境下切换接口地址。将接口域名配置为全局变量可以方便地管理和修改接口地址。下面是实现这一目标的完整攻略。 步骤一:创建配置文件 首先,我们需要创建一个配置文件来存储接口域名。在项目的根目录下创建一个名为config.js的文件,并在其中定义一个全局变量API_BA…

    other 2023年7月29日
    00
  • 四个例子说明C语言 全局变量

    C语言全局变量的完整攻略 全局变量是在函数外部定义的变量,可以在程序的任何地方使用。在C语言中,全局变量具有以下特点: 全局作用域:全局变量在整个程序中都是可见的,可以被任何函数访问和修改。 静态存储持续性:全局变量在程序运行期间一直存在,直到程序结束才会被销毁。 默认初始化:如果没有显式地对全局变量进行初始化,它们会被默认初始化为0。 下面通过四个例子来详…

    other 2023年7月28日
    00
  • go-zero 应对海量定时/延迟任务的技巧

    如何应对海量定时/延迟任务是一个常见的技术挑战,下面将介绍如何使用go-zero来解决这个问题。主要包括以下几个方面:使用redis实现定时/延迟任务,使用go-zero的timer来统计任务执行时间,使用chan优化任务并发量。 使用redis实现定时/延迟任务 一般需要用到定时/延迟任务的场景不会只有一个,而是会有很多。如果我们在应用程序自己写定时/延迟…

    other 2023年6月27日
    00
  • lombok 子类中如何使用@Builder问题

    在Lombok中,@Builder是一个非常方便的注解,它可以快速地生成Builder模式的代码,使代码变得更加优雅和简洁。但是,当我们在子类中使用@Builder时,可能会遇到一些困惑和问题。本文将详细讲解在Lombok子类中如何使用@Builder。 1. 使用@NoArgsConstructor注解 在子类中使用@Builder时,我们必须在父类中使用…

    other 2023年6月26日
    00
  • IntelliJ IDEA 2019如何匹配大小写开关?IntelliJ IDE匹配大小写开关教程

    IntelliJ IDEA 2019如何匹配大小写开关? 在IntelliJ IDEA 2019中,你可以通过以下步骤来开启或关闭匹配大小写功能: 打开IntelliJ IDEA 2019。 在菜单栏中选择 \”File\”(文件)。 从下拉菜单中选择 \”Settings\”(设置)。 在弹出的窗口中,选择 \”Editor\”(编辑器)。 在左侧的面板中…

    other 2023年8月16日
    00
  • sip错误代码503

    当SIP服务器无法处理请求时,会返回错误代码503。在本教程中,我们将详细介绍SIP错误代码503的含义、原因和解决方法。 SIP错误代码503含义 SIP错误代码503表示服务器暂时无法处理请求。这通常是由于服务器过载或维护而导致的。当客户收到503错误代码时,它应该尝试重新发送请求。 SIP错误代码503的原因 SIP错误代码503通常是由以下原因一引起…

    other 2023年5月7日
    00
  • 关于计算机科学:启发式和元启发式之间有什么区别?

    以下是关于“关于计算机科学:启发式和元启发式之间有什么区别?”的完整攻略,过程中包含两个示例。 背景 在计算机科学中,启发式和元启发式是两个常用的概念。它们都是指一种问题求解的方法,但它们之间有一些别。 启发式 启发式是一种问题求解的方法,它基于经验和直觉,而不是严格的算法或学模型。启发式算法通常用于解决那些难以用传统算法解决的问题。启发式算法的优点是速度快…

    other 2023年5月9日
    00
  • 使用批处理命令设置windows系统的ip地址和dns附图

    当你需要使用批处理命令设置Windows系统的IP地址和DNS时,可以按照以下步骤进行操作: 打开文本编辑器,例如记事本,创建一个新的批处理文件(以.bat为扩展名)。 在批处理文件中,使用以下命令来设置IP地址和子网掩码: netsh interface ipv4 set address name=\”本地连接\” static IP地址 子网掩码 其中,…

    other 2023年7月30日
    00
合作推广
合作推广
分享本页
返回顶部