【数据结构】线性表(十)队列:循环队列及其基本操作(初始化、判空、判满、入队、出队、存取队首元素)

news2024/12/24 22:12:03

文章目录

  • 队列
    • 1. 定义
    • 2. 基本操作
  • 顺序队列
  • 循环队列
    • 1. 头文件和常量
    • 2. 队列结构体
    • 3. 队列的初始化
    • 4. 判断队列是否为空
    • 5. 判断队列是否已满
    • 6. 入队
    • 7. 出队
    • 8. 存取队首元素
    • 9. 获取队列中元素个数
    • 10. 打印队列中的元素
    • 9. 主函数
    • 10. 代码整合

  堆栈Stack 和 队列Queue是两种非常重要的数据结构,两者都是特殊的线性表:

  • 对于堆栈,所有的插入和删除(以至几乎所有的存取)都是在表的同一端进行;
  • 对于队列,所有的插入都是在表的一端进行,所有的删除(以至几乎所有的存取)都是在表的另一端进行。

队列

1. 定义

  队列是一种操作受限的线性表,对于它的所有插入都在表的一端进行,所有的删除(以至几乎所有的存取)都在表的另一端进行,且这些操作又都是按照先进先出(FIFO)的原则进行的。进行删除的一端称为队头(front),进行插入的一端称为队尾(rear)。没有元素的队列称为空队列(简称空队)。

在这里插入图片描述
  队列就像生活中排队购物,新来的人只能加入队尾(假设不允许插队),购物结束后先离开的总是队头(假设无人中途离队)。也就是说,先加入队列的成员总是先离开队列,因此队列被称为先进先出(First In First Out)的线性表,简称为FIFO表。如图,在空队列中依次加入元素a1,a2,a3,a4,a5,出队次序仍然是a1,a2,a3,a4,a5 .

2. 基本操作

  • 队列是受限的线性表,其基本操作包括

    • IsEmpty() : 判断队列是否为空;
    • isFull():判断队列是否为满;
    • enqueue() :向队尾添加元素(入队);
    • dequeue() :删除队首元素(出队);
    • peek():获取队首的元素值(存取);
  • 同普通线性表一样,队列也可以用顺序存储和链接存储两种方式来实现:

顺序队列

  参考前文:线性表(八)队列:顺序队列及其基本操作(初始化、判空、判满、入队、出队、存取队首元素)

  关于顺序队列,删除队头元素有两种方式:

  • ⑴ 不要求队头元素必须存放在数组的第一个位置。每次删除队头元素,只需修改队头指针front所指的位置(即队头元素在数组中的下标),令front=front+1 . 该方式的优点是无须改变诸队列元素的地址,缺点是front值随着队头元素的删除而不断增加,整个队列向数组的后端位置移动,随着队尾元素的不断加入,必然出现数组后端没有可用空间的情况,而数组前端的大量空间却被闲置。
  • ⑵ 要求队头元素必须存放在数组的第一个位置。每次删除队头元素,令所有元素都向前移动一个位置。该方式的优点是不浪费空间,缺点是所有元素的地址都必须改变,效率低下。

循环队列

  为了克服上述缺点,可以假定数组是循环的,即采用环状模型来实现顺序队列。这种模型将队列在逻辑上置于一个圆环上,如图3.17所示,用整型变量front存放队头位置,每删除一个队头元素,就将front顺时针移动一个位置;整型变量rear存放新元素要插入的位置(下标),每插入一个元素,rear将顺时针移动一个位置;整型变量count存放队列中元素的个数,当count等于数组规模Size时,说明队列已满,当count等于0时,说明队列为空。
在这里插入图片描述

1. 头文件和常量

#include <stdio.h>
#define MAX_SIZE 100
  • 头文件stdio.h用于输入输出操作

  • 通过#define指令定义了一个常量MAX_SIZE,它表示顺序队列中数组的最大容量为100

2. 队列结构体

typedef struct {
    int data[MAX_SIZE]; // 存储队列元素的数组
    int front;          // 队头指针
    int rear;           // 队尾指针
    int count;          // 队列规模
} CircularQueue;
  • 整型数组 data,用于存储队列元素;
  • frontrear 分别表示队头指针和队尾指针;
  • count:队列中元素的个数。

3. 队列的初始化

void initQueue(CircularQueue *queue) {
    queue->front = 0;
    queue->rear = 0;
    queue->count = 0;
}

   initQueue 函数:初始化队列,它将队头、队尾和元素个数都设置为0,表示队列为空。

4. 判断队列是否为空

bool isEmpty(CircularQueue *queue) {
//    return queue->front == 0;
    return queue->count == 0;
}

   通过检查队列中元素的个数来判断队列是否为空。

5. 判断队列是否已满

bool isFull(CircularQueue *queue) {
    return queue->count == MAX_SIZE;
}

  通过比较队列中元素的个数和最大容量 MAX_SIZE 来判断队列是否已满。

6. 入队

void enqueue(CircularQueue *queue, int item) {
    if (isFull(queue)) {
        printf("Queue is full. Cannot enqueue.\n");
        return;
    }
    queue->data[queue->rear] = item;
    queue->rear = (queue->rear + 1) % MAX_SIZE;
    queue->count++;
}
  • 判断队列是否已满
    • 如果已满则打印错误信息并返回;
    • 否则,将元素添加到队尾,并更新队尾指针和元素个数。

7. 出队

int dequeue(CircularQueue *queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty. Cannot dequeue.\n");
        return -1;
    }

    int item = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_SIZE;
    queue->count--;

    return item;
}

  • 判断队列是否为空
    • 如果为空则打印错误信息并返回 -1;
    • 否则,将队头元素返回,并更新队头指针和元素个数。

8. 存取队首元素

int peek(CircularQueue *queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty. Cannot peek.\n");
        return -1;
    }

    return queue->data[queue->front];
}

   peek 函数用于查看队头元素,但不移除它。如果队列为空,则打印提示信息并返回 -1。

9. 获取队列中元素个数

int size(CircularQueue *queue) {
    return queue->count;
}

10. 打印队列中的元素

void display(CircularQueue *queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty.\n");
        return;
    }

    printf("Queue elements: ");
    int i = queue->front;
    int count = 0;
    while (count < queue->count) {
        printf("%d ", queue->data[i]);
        i = (i + 1) % MAX_SIZE;
        count++;
    }
    printf("\n");
}

  • 如果队列为空,则打印提示信息;
  • 否则,使用循环遍历队列中的元素并逐个打印。

9. 主函数

int main() {
    CircularQueue queue;
    initQueue(&queue);

    enqueue(&queue, 1);
    enqueue(&queue, 2);
    enqueue(&queue, 3);

    display(&queue);
    printf("Queue size: %d\n", size(&queue));
    printf("Front element: %d\n", peek(&queue));

    dequeue(&queue);
    printf("Dequeued element.\n");

    display(&queue);
    printf("Queue size: %d\n", size(&queue));
    printf("Front element: %d\n", peek(&queue));

    return 0;
}

在这里插入图片描述

10. 代码整合

#include <stdio.h>

#define MAX_SIZE 100


typedef struct {
    int data[MAX_SIZE]; // 存储队列元素的数组
    int front;          // 队头指针
    int rear;           // 队尾指针
    int count;          // 队列规模
} CircularQueue;

void initQueue(CircularQueue *queue) {
    queue->front = 0;
    queue->rear = 0;
    queue->count = 0;
}

bool isEmpty(CircularQueue *queue) {
//    return queue->front == 0;
    return queue->count == 0;
}

bool isFull(CircularQueue *queue) {
    return queue->count == MAX_SIZE;
}

void enqueue(CircularQueue *queue, int item) {
    if (isFull(queue)) {
        printf("Queue is full. Cannot enqueue.\n");
        return;
    }

    queue->data[queue->rear] = item;
    queue->rear = (queue->rear + 1) % MAX_SIZE;
    queue->count++;
}

int dequeue(CircularQueue *queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty. Cannot dequeue.\n");
        return -1;
    }

    int item = queue->data[queue->front];
    queue->front = (queue->front + 1) % MAX_SIZE;
    queue->count--;

    return item;
}

int peek(CircularQueue *queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty. Cannot peek.\n");
        return -1;
    }

    return queue->data[queue->front];
}

int size(CircularQueue *queue) {
    return queue->count;
}

void display(CircularQueue *queue) {
    if (isEmpty(queue)) {
        printf("Queue is empty.\n");
        return;
    }

    printf("Queue elements: ");
    int i = queue->front;
    int count = 0;
    while (count < queue->count) {
        printf("%d ", queue->data[i]);
        i = (i + 1) % MAX_SIZE;
        count++;
    }
    printf("\n");
}

int main() {
    CircularQueue queue;
    initQueue(&queue);

    enqueue(&queue, 1);
    enqueue(&queue, 2);
    enqueue(&queue, 3);

    display(&queue);
    printf("Queue size: %d\n", size(&queue));
    printf("Front element: %d\n", peek(&queue));

    dequeue(&queue);
    printf("Dequeued element.\n");

    display(&queue);
    printf("Queue size: %d\n", size(&queue));
    printf("Front element: %d\n", peek(&queue));

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1123685.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

首次扭亏为盈后,货拉拉还想靠造车更上一层楼?

前阵子&#xff0c;一句【货拉拉“拉不拉”拉布拉多&#xff0c;取决于货拉拉“拉”拉布拉多时拉布拉多“拉”得多不多】的趣梗在网上掀起了一波热潮。而热梗背后的主角货拉拉&#xff0c;近期又透露出了谋求港股上市的消息&#xff0c;进而在市场上又掀起了一波热潮。 招股书…

Java拦截器(Interceptor)和过滤器(Filter)实例详解

一、Java过滤器和拦截器 1.1、过滤器(Filter) Filter过滤器&#xff0c;是Servlet&#xff08;Server Applet&#xff09;技术中的技术&#xff0c;开发人员可以通过Filter技术&#xff0c;管理web资源&#xff0c;可以对指定的一些行为进行拦截&#xff0c;例如URL级别的权限…

程序员的金饭碗在哪里?这几个网站建议收藏!帮助你一步登天

俗话说的好&#xff0c;一个趁手的工具抵过诸葛亮。尤其是在程序员这个领域&#xff0c;不仅是一个非常和科技挂钩的领域&#xff0c;而且更新速度非常的迅速。 连java python都在更新&#xff0c;手头上写码的工具却还是老三样怎可行&#xff1f;这就需要我们跟上时代的脚步&…

全局下载报错怎么办

举个例子&#xff0c;当你要全局下载create-react-app&#xff0c;报如下图所示的错 这个时候&#xff0c;关闭掉git base,再以管理员身份运行 你再次下载&#xff0c;ok了

【网络】对于我前面UDP博客的补充

UDP 前言正式开始UDP报文UDP报文如何将UDP报文和报头进行分离和封装UDP如何将有效载荷交付给上层如何提取出完整报文报头是啥报头中的检验和 UDP的特点IO接口乱序问题UDP是全双工的注意事项基于UDP的应用层协议 再次谈论端口五元组端口号范围划分netstatxargs 前言 本篇比较偏…

C#调用C++ 的DLL传送和接收中文字符串

1 c#向c传送中文字符串 设置&#xff1a;将 字符集 改为 使用多字节字符集 cpp代码&#xff1a; extern "C"_declspec(dllexport) int input_chn_str(char in_str[]) {cout<<in_str<<endl;return 0; }c#代码&#xff1a; [DllImport("Demo.dll…

uni-app:引用文件的方法

绝对定位 ①import common from "/utils/common.js" ②import common from "utils/common.js" <template><view></view> </template> <script>import common from "/utils/common.js"export default {data() {ret…

分享一下抽奖活动小程序怎么做

在当今数字化时代&#xff0c;抽奖活动小程序已成为一种高效、创新的营销方式。它不仅能够吸引用户的注意力&#xff0c;提高品牌知名度&#xff0c;还能促进用户参与度&#xff0c;增强用户对品牌的忠诚度。本文将详细介绍如何制作一个成功的抽奖活动小程序&#xff0c;以及它…

[yolo系列:如何固定随机种子(以yolov7为例)]

文章目录 概要随机种子&#xff08;Random Seed&#xff09;第一步第二步第三步第四步 概要 在计算机科学和深度学习领域&#xff0c;随机性是一个常见而重要的概念。在一些情况下&#xff0c;我们需要确保代码每次运行时都能得到相同的随机结果&#xff0c;以便进行模型的可重…

SAR ADC:10 bit 串口控制的模数转换器MS1549,可替TLV1549

MS1549 是一个 10 位开关电容器、逐次逼近型的模数转换 器。此芯片有 2 个数字输入端、 1 个三态输出口&#xff08;包括片选端 口 ( CS ) 、 1 个 I/O CLOCK 端口和 1 个数字输出端 (DATA OUT) &#xff09;&#xff0c; 可以实现三总线接口到总控制器的串行口的数据传输…

正点原子嵌入式linux驱动开发——异步通知

上一篇笔记中使用阻塞或者非阻塞的方式来读取驱动中按键值都是应用程序主动读取的&#xff0c;对于非阻塞方式来说还需要应用程序通过poll函数不断的轮询。最好的方式就是驱动程序能主动向应用程序发出通知&#xff0c;报告自己可以访问&#xff0c;然后应用程序再从驱动程序中…

Redis持久化解析:全面了解Redis的数据持久化机制

文章目录 &#x1f34a; Redis持久化&#x1f389; 什么是持久化&#xff1f;&#x1f389; 持久化的原理&#x1f4dd; RDB持久化&#x1f4dd; AOF持久化&#x1f4dd; 混合持久化&#x1f4dd; save与bgsave &#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、Java领…

使用 VS 2022 开发C#项目的tips

代码操作 删除注释或空行 参考C#【必备技能篇】Visual Studio删除所有的注释和空行 删除所有行注释&#xff1a;包括行内和行外&#xff0c;如下所示 Ctrl H 替换&#xff0c;第一行输入&#xff1a;//[^\n]*\n, 第二行输入&#xff1a;\n。替换即可。 这一步可能出现很多空…

数据结构题型20-第七章 查找

文章目录 1 考察重点2 知识框架3 考察重点4 顺序查找和折半查找4.1 顺序查找4.1.1 一般线性表的顺序查找4.1.2 有序表的顺序查找 4.2 折半查找4.3 分块查找 1 考察重点 2 知识框架 3 考察重点 4 顺序查找和折半查找 4.1 顺序查找 4.1.1 一般线性表的顺序查找 4.1.2 有序表的顺…

基于Django开发的图书管理推荐、电影推荐、课程推荐系统、大众点评店铺推荐系统、健身课程管理系统

基于Django开发的图书管理推荐、电影推荐、课程推荐系统、大众点评店铺推荐系统、健身课程管理系统、资讯推荐系统 一、简介 推荐系统的目的是信息过载所采用的措施&#xff0c;面对海量的数据&#xff0c;从中快速推荐出用户可能喜欢的物品。 推荐系统的方法有以下几种&…

顺序栈的实现----数据结构

栈的概念 对于栈&#xff08;Stack&#xff09;&#xff0c;后进先出&#xff08;Last In First Out&#xff0c;LIFO&#xff09;&#xff0c;栈也是一种线性表&#xff0c;只不过是一种操作受限的线性表&#xff0c;只能在一端操作&#xff0c;也就是不允许在中间进行查找、…

javaEE -4(11000字详解多线程)

一&#xff1a;常见的锁策略 1.1 乐观锁 vs 悲观锁 乐观锁和悲观锁是并发控制的两种不同策略&#xff0c;用于处理多个线程同时访问共享资源的情况。它们的主要区别在于对并发冲突的处理方式。 悲观锁是一种较保守的并发控制策略&#xff0c;它假设在整个事务过程中会发生冲…

什么是云迁移?迁移到云的基本指南

企业可以执行多种类型的云迁移。一种常见的模型是将数据和应用从本地数据中心传输到公共云。然而&#xff0c;云迁移还可能需要将数据和应用从一个云平台或提供商迁移到另一个云平台或提供商;这种模式称为云到云(C2C)迁移。第三种类型的迁移是反向云迁移、云遣返或云退出&#…

如何提高webpack的构建速度?

一、背景 随着我们的项目涉及到页面越来越多&#xff0c;功能和业务代码也会随着越多&#xff0c;相应的 webpack 的构建时间也会越来越久 构建时间与我们日常开发效率密切相关&#xff0c;当我们本地开发启动 devServer 或者 build 的时候&#xff0c;如果时间过长&#xff…

Linux下的IMX6ULL——环境搭建与软件安装(一)

前言&#xff1a; 从今天开始我们就要用到IMX6ULL这块开发板进行linux的学习了&#xff0c;对于初学者&#xff0c;下载好资料、搭建好开发环境后&#xff0c;按照下面顺序学习即可&#xff1a; 先应用&#xff0c;再驱动&#xff0c;最后做项目。应用、驱动、项目这三个慢慢走…