C语言实现循环队列

C语言实现循环队列的完整攻略

前言

循环队列是一种常用的数据结构,用于解决队列数据访问时线性存储空间限制的问题。本文将讲解如何使用C语言实现循环队列。

队列的定义

队列是一种特殊的线性表,具有先进先出(FIFO)的特点,即最先进入队列的元素最先被取出。

循环队列的特殊之处在于,队列空间是使用连续的线性存储空间而形成的一个环。

循环队列的实现

代码实现

在C语言中,循环队列的实现可通过以下代码实现:

// 声明循环队列结构体
typedef struct {
    int* data;  // 指向队列数据域的指针
    int front;  // 队头指针
    int rear;   // 队尾指针
    int size;   // 队列大小
} CircularQueue;

// 初始化循环队列
CircularQueue* InitCircularQueue(int size) {
    CircularQueue* queue = (CircularQueue*)malloc(sizeof(CircularQueue));
    queue->data = (int*)malloc(sizeof(int) * size);
    queue->front = queue->rear = 0;
    queue->size = size;
    return queue;
}

// 判断循环队列是否为空
bool IsCircularQueueEmpty(CircularQueue* queue) {
    return queue->front == queue->rear;
}

// 判断循环队列是否已满
bool IsCircularQueueFull(CircularQueue* queue) {
    return (queue->rear + 1) % queue->size == queue->front;
}

// 往循环队列中添加元素
int AddCircularQueue(CircularQueue* queue, int value) {
    if (IsCircularQueueFull(queue)) {
        return -1;  // 队列已满,无法添加元素
    }
    queue->data[queue->rear] = value;
    queue->rear = (queue->rear + 1) % queue->size;
    return 0;
}

// 从循环队列中取出元素
int RemoveCircularQueue(CircularQueue* queue, int* value) {
    if (IsCircularQueueEmpty(queue)) {
        return -1;  // 队列为空,无法取出元素
    }
    *value = queue->data[queue->front];
    queue->front = (queue->front + 1) % queue->size;
    return 0;
}

// 销毁循环队列,释放内存空间
void DestroyCircularQueue(CircularQueue* queue) {
    free(queue->data);
    free(queue);
}

代码说明

上述代码中,定义了一个CircularQueue类型的结构体,其中包含了指向队列数据域的指针data,队头指针front,队尾指针rear,队列大小size四个成员。

接着,使用InitCircularQueue函数初始化循环队列,并在其中调用malloc函数分配数据空间,最后返回循环队列的指针。

在进行队列操作时,通过AddCircularQueue函数往队列中添加元素,通过RemoveCircularQueue函数将队列中的元素取出。

需要说明的是,为了避免“队尾指针指向数据空间的尾部而未满,队头指针指向数据空间的头部而为空”的歧义情况,循环队列中将队列的尾部指针(rear)指向下一个数据存放的位置。因此,判断队列是否为空的条件为队头指针(front)与队尾指针(rear)相等,而判断队列是否为满的条件为队列的下一位为队头指针(front)。

示例说明

示例1:使用循环队列解决Josephus问题

Josephus问题是一个著名的数学游戏,有N个人围成一圈,编号从1到N,从某个编号开始报数,数到M的人出列,之后从下一个人开始重新报数。求出最后留下的人的编号。

使用循环队列可以轻松地解决Josephus问题。下面是C语言实现代码及注释:

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

// 声明循环队列结构体
#include "circlequeue.h"

int main() {
    int N = 10;   // 总人数
    int M = 3;    // 报数的周期
    int i, j;
    int e, a[N];  // 声明临时变量和数组
    CircularQueue* q;  // 声明循环队列指针
    q = InitCircularQueue(N);  // 初始化循环队列
    for (i = 0; i < N; i++) {
        AddCircularQueue(q, i + 1);  // 将人员编号依次加入队列
    }
    for (i = 0; i < N; i++) {
        RemoveCircularQueue(q, &e);  // 模拟报数,出队列
        a[i] = e;  // 将出队列的人员编号存放到数组中
        for (j = 1; j < M; j++) {
            RemoveCircularQueue(q, &e);  // 模拟报数,不出队列
            AddCircularQueue(q, e);      // 将不出队列的人员重新加入队列
        }
    }
    printf("出列顺序:");
    for (i = 0; i < N; i++) {
        printf("%d ", a[i]);  // 输出出列顺序
    }
    printf("\n最后留下:%d\n", e);  // 输出最后留下的人员编号
    DestroyCircularQueue(q);  // 删除队列,释放内存空间
    return 0;
}

示例2:使用循环队列模拟打印任务调度

使用循环队列可以方便地模拟打印任务的调度。下面是C语言实现代码及注释:

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

// 声明循环队列结构体
#include "circlequeue.h"

int main() {
    int max_task_num = 6;   // 最大任务数
    int task_left = 0;      // 等待执行的任务数
    int executing_task_id;  // 当前正在执行的任务ID
    int i;
    CircularQueue* queue;   // 声明循环队列指针
    queue = InitCircularQueue(max_task_num);  // 初始化循环队列
    while (1) {
        printf("\n********************\n");      
        printf("等待任务:%d,", task_left);  // 打印等待任务数
        if (!IsCircularQueueEmpty(queue)) {
            printf("队列头部任务:[%d]\n", queue->data[queue->front]);  // 打印队列中最前面的任务
        } else {
            printf("无任务\n");  // 如果队列为空则输出“无任务”
        }
        printf("********************\n\n");      

        // 获取用户输入
        printf("请输入命令(a-添加任务,e-执行任务):");
        char cmd = getchar();
        while (getchar() != '\n')
            ;
        if (cmd == 'a') {  // 添加任务
            if (!IsCircularQueueFull(queue)) {
                AddCircularQueue(queue, max_task_num - task_left);  // 添加任务ID
                task_left++;  // 可执行任务数加1
                printf("添加成功,当前等待任务:%d\n", task_left);
            } else {
                printf("任务队列已满,无法添加任务\n");
            }
        } else if (cmd == 'e') {  // 执行任务
            if (!IsCircularQueueEmpty(queue)) {
                RemoveCircularQueue(queue, &executing_task_id);  // 取出队列中最前面的任务
                task_left--;  // 可执行任务数减1
                printf("任务[%d]开始执行,当前等待任务:%d\n", executing_task_id, task_left);
            } else {
                printf("任务队列为空,无法执行任务\n");
            }
        } else {
            printf("无效命令\n");
        }
    }
    DestroyCircularQueue(queue);  // 删除队列,释放内存空间
    return 0;
}

总结

本文介绍了C语言如何实现循环队列,包括定义循环队列结构体、初始化循环队列、判断队列是否为空、判断队列是否已满、往队列中添加元素、从队列中取出元素、销毁循环队列等操作。

同时,本文还提供了两个使用循环队列的示例:使用循环队列解决Josephus问题和使用循环队列模拟打印任务调度。这些示例可以帮助读者更好地理解和应用循环队列。

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

(0)
上一篇 2023年5月23日
下一篇 2023年5月23日

相关文章

  • C++ boost::asio编程-异步TCP详解及实例代码

    下面我将详细介绍一下“C++ boost::asio编程-异步TCP详解及实例代码”的完整攻略,包括相关知识点和两个示例说明。 一、boost::asio异步编程基础 1.1 异步和同步 同步:调用函数后程序会等待函数返回结果后再执行下一步操作。 异步:调用函数后程序不会等待函数返回结果,而是立即执行下一步操作。函数的返回结果则由另一个线程或者回调函数处理并…

    C 2023年5月23日
    00
  • springboot项目数据库密码如何加密

    首先,为了保证数据库密码的安全性,我们可以在SpringBoot项目中使用加密算法对数据库密码进行加密。以下是实现步骤: 1.引入依赖 在项目的pom.xml文件中引入Jasypt的依赖: <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifa…

    C 2023年5月23日
    00
  • 使命召唤手游怎么赚c币 C币获取方法一览

    使命召唤手游怎么赚C币:C币获取方法一览 什么是C币? C币是使命召唤手游中的虚拟货币,可以用来购买游戏内道具和装备。 C币获取方法 1. 完成任务 游戏中会有一些每日和成就任务,每完成一项可获得一定数量的C币作为奖励。在任务界面查看任务并完成就可以领取奖励。 2. 参加活动 游戏官方会举办一些活动,参加活动并完成指定要求可以获取C币奖励。活动类型包括临时活…

    C 2023年5月23日
    00
  • 内存的存储及其存储方式

    1. 内存存储2. 内存存储的方式3.为什么要有大小端模式的区分4.判断大小端模式 1.内存的存储:内存是由低地址向高地址进行存储。(即我们个位数为低地址位,而百,千位为高地址数) 为方便理解我们定义了一个变量a,如下 vs上方窗口栏:调试–>窗口–>内存–>内存1 在地址处输入&a,取a的地址 内存存储总结:我们可以看到数据…

    C语言 2023年4月18日
    00
  • C 标准库 float.h

    C 标准库的 float.h 头文件包含了浮点型数值的一些有用的常量和宏定义。这些常量和宏定义可以帮助我们在程序中进行更精确的浮点数计算。 下面是一些 float.h 头文件中常用的常量和宏定义: 常量 FLT_RADIX:浮点数基数,即底数的数值。 FLT_MANT_DIG:最大二进制位数,通常是23。 DBL_MANT_DIG:一个 double 类型变…

    C 2023年5月10日
    00
  • 哈利波特4 火焰杯游戏流程全攻略

    哈利波特4 火焰杯游戏流程全攻略 简介 哈利波特4 火焰杯是一款基于小说改编的动作冒险游戏,旨在让玩家体验哈利波特的学校生活,以及参加一系列危险的魔法比赛。本攻略将为玩家介绍游戏的全流程,包括人物控制、任务完成以及游戏机制等方面,以帮助玩家更好地理解游戏并顺利通关。 游戏机制 在游戏中,玩家将扮演哈利波特,探索霍格沃茨学院的各个角落,完成各种任务和挑战。游戏…

    C 2023年5月22日
    00
  • 深入浅出讲解Java比较器及数学常用类

    深入浅出讲解Java比较器及数学常用类 Java比较器 Java中的比较器是用于比较两个对象的大小关系的接口,它定义了一个compare()方法用于比较大小。常用于排序、查找等场景中。 自然排序 自然排序是Java中默认的排序方式,即根据对象所属类型的大小关系进行排序。例如,整数类型按照数值大小进行排序,字符串类型按照字典序进行排序。 public clas…

    C 2023年5月22日
    00
  • C++实现简易反弹小球游戏的示例代码

    好的。首先,让我们来讲解如何使用C++实现简易反弹小球游戏的完整攻略。 准备工作 在开始编写代码之前,我们需要准备一些工具和环境: C++编译器(建议使用Visual Studio等集成开发环境) 游戏引擎或者相关库(例如SDL2等) 在本篇攻略中,我们将使用SDL2库来实现我们的游戏。因此,在开始之前,我们需要安装SDL2库及其所需的依赖项。 编写代码 接…

    C 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部