数据结构(五)队列

news2024/11/15 19:36:08

文章目录

  • 一、概念
  • 二、逻辑结构:线性结构
  • 三、存储结构
    • (一)顺序队列
    • (二)循环队列
      • 1. 结构体定义
      • 2. 创建队列
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 3. 入队列
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 4. 出队列
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 5. 清空和销毁
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 6. 打印
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
    • (三)链式队列
      • 1. 结构体定义
      • 2. 创建队列
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 3. 入队列
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 4. 出队列
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 5. 清空和销毁
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
      • 6. 打印
        • (1)函数定义
        • (2)注意点
        • (3)代码实现
  • 四、所有源代码已上传至我的资源

一、概念

队列是一种先入先出的结构(FIFO — first in first out)

二、逻辑结构:线性结构

三、存储结构

(一)顺序队列

顺序队列是基于 一个数组配合着两个下标(队列头front、队列尾rear)来实现的
顺序队列的本质就是对顺序表操作的一个约束:只能在一端插入 另一端删除
图片1

这种队列我们一般不直接使用,因为 入队列时rear++ 出队列时front++
相当于每块空间只使用了一次,即使数据出队列了,空间也不会被复用了,相当于一次性的队列

(二)循环队列

循环队列相当于顺序队列的一个小优化,目的是让空间复用起来
循环队列相当于是对顺序队列的一个小的优化,目的是让空间能复用起来。
图片

这种队列就能让空间复用起来了。
每次数据入队列后,不要直接执行 rear++ 而是改成 rear = (rear+1)%N
每次数据出队列后,不要直接执行 front++ 而是改成 front = (front+1)%N

判断队列为空 front == rear ,如下图,即认为队列空
在这里插入图片描述

判断队列为满 (rear+1)%N == front (浪费了一个存储空间 方便区分队列满 和 队列空),如下图,即认为队列已满
在这里插入图片描述

1. 结构体定义

typedef struct _Queue{
    int s[N];
    int front;
    int rear;
}queue_t;

2. 创建队列

(1)函数定义

int create_queue(queue_t **my_queue);

(2)注意点
(3)代码实现
int create_queue(queue_t **my_queue){
    if(NULL==my_queue) return -1;
    *my_queue=(queue_t *)malloc(sizeof(queue_t));
    if(NULL==*my_queue) return -1;
    //初始化
    (*my_queue)->front=0;
    (*my_queue)->rear=0;
    return 0;
}

3. 入队列

(1)函数定义

int is_full(queue_t *my_queue);
int push_queue(queue_t *my_queue,int num);

(2)注意点
(3)代码实现
//满为1,空为0
int is_full(queue_t *my_queue){
    if(NULL==my_queue) return -1;
    return (my_queue->rear+1)%N==my_queue->front?1:0;
}

//入队列
int push_queue(queue_t *my_queue,int num){
    if(NULL==my_queue) return -1;
    if(is_full(my_queue)){
        printf("队列满\n");
        return -1;
    }
    my_queue->s[my_queue->rear]=num;
    my_queue->rear=(my_queue->rear+1)%N;
    return 0;
}

4. 出队列

(1)函数定义

int is_empty(queue_t *my_queue);
int pop_queue(queue_t *my_queue,int num);

(2)注意点
(3)代码实现
//空为1,不空为0
int is_empty(queue_t *my_queue){
    if(NULL==my_queue) return -1;
    return my_queue->rear==my_queue->front?1:0;
}

int pop_queue(queue_t *my_queue,int *num){
    if(NULL==my_queue || NULL==num) return -1;
    if(is_empty(my_queue)){
        printf("队列空\n");
        return -1;
    }
    *num=my_queue->s[my_queue->front];
    my_queue->front=(my_queue->front+1)%N;
}

5. 清空和销毁

(1)函数定义

int clean_queue(queue_t *my_queue)
int destroy_queue(queue_t **my_queue);

(2)注意点
(3)代码实现
int clean_queue(queue_t *my_queue){
    if(NULL==my_queue) return -1;
    my_queue->rear=my_queue->front;
    return 0;
}

int destroy_queue(queue_t **my_queue){
    if(NULL==my_queue || NULL==*my_queue) return -1;
    free(*my_queue);
    *my_queue=NULL;
    return 0;
}

6. 打印

(1)函数定义

int print_queue(queue_t *my_queue);

(2)注意点
(3)代码实现
int print_queue(queue_t *my_queue){
    if(NULL==my_queue) return -1;
    /**也可以写成这种形式
    *for(int i=my_queue->front;i!=my_queue->rear;i=(i+1)%N){
    *	printf("%d ",my_queue->s[i]);
    *}
    **/
    int temp=my_queue->front;
    while(temp!=my_queue->rear){
        printf("%d ",my_queue->s[temp]);
        temp=(temp+1)%N;
    }
    putchar(10);
    return 0;
}

(三)链式队列

逻辑结构:线性结构
存储结构:链式存储,在内存中不连续

1. 结构体定义

//数据元素的结构体
typedef struct _Node{
    int data;
    struct _Node *next;
}node_t;

//队列的结构体
typedef struct _Queue{
    node_t *front;
    node_t *rear;
}queue_t;

2. 创建队列

(1)函数定义

int create_queue(queue_t **my_queue);

申请一块数据对象的内存空间
初始化

(2)注意点
  1. 初始化时,front和rear指针均为NULL
(3)代码实现
int create_queue(queue_t **my_queue){
    if(NULL==my_queue) return -1;
    *my_queue=(queue_t *)malloc(sizeof(queue_t));
    if(NULL==*my_queue) return -1;
    //初始化
    (*my_queue)->front=NULL;
    (*my_queue)->rear=NULL;

    return 0;
}

3. 入队列

(1)函数定义

int push_queue(queue_t *my_queue,int num);

申请一块数据元素的内存空间
采用尾插

(2)注意点
  1. 插入第一个节点时,需要将front和rear都指向第一个节点
  2. 其他节点采用尾插的方法,front无需改变
(3)代码实现
//尾插,无需判断是否满
int push_queue(queue_t *my_queue,int num){
    if(NULL==my_queue) return -1;
    node_t *p=(node_t *)malloc(sizeof(node_t));
    if(NULL==p) return -1;
    p->next=NULL;
    p->data=num;
    //插入第一个节点
    if(NULL==my_queue->front){
        my_queue->front=p;
        my_queue->rear=p;
        return 0;
    }
    //插入其他节点,头节点不变
    my_queue->rear->next=p;
    my_queue->rear=p;
    return 0;
}

4. 出队列

(1)函数定义

int is_empty(queue_t *my_queue);
int pop_queue(queue_t *my_queue,int num);

(2)注意点
  1. 头删,需要判断队列是否为空,当my_queue->front为NULL时说明队列空
  2. 只有一个元素时,删除它时front和rear指针均需要置NULL
(3)代码实现
int is_empty(queue_t *my_queue){
    if(NULL==my_queue) return -1;
    return my_queue->front==NULL?1:0;
}
int pop_queue(queue_t *my_queue,int *num){
    if(NULL==my_queue||NULL==num) return -1;
    if(is_empty(my_queue)){
        printf("栈空\n");
        return -1;
    }
    //只有一个元素
    if(my_queue->front==my_queue->rear){
        *num=my_queue->front->data;
        free(my_queue->front);
        my_queue->front=NULL;
        my_queue->rear=NULL;
        return 0;
    }
    //有多个元素
    node_t *ptemp=my_queue->front;
    *num=my_queue->front->data;
    my_queue->front=my_queue->front->next;
    free(ptemp);
    ptemp=NULL;
    return 0;
}

5. 清空和销毁

(1)函数定义

int clean_queue(queue_t *my_queue)
int destroy_queue(queue_t **my_queue);

(2)注意点
  1. 清空是释放所有元素的节点空间
  2. 销毁是先清空,然后释放数据对象的空间
(3)代码实现
int clean_queue(queue_t *my_queue){
    if(NULL==my_queue) return -1;
    node_t *ptemp=NULL;
    while(my_queue->front!=NULL){
        ptemp=my_queue->front;
        my_queue->front=my_queue->front->next;
        free(ptemp);
    }
    ptemp=NULL;
    my_queue->rear=NULL;
    return 0;
}

int destroy_queue(queue_t **my_queue){
    if(NULL==my_queue||NULL==*my_queue) return -1;
    clean_queue(*my_queue);
    free(*my_queue);
    *my_queue=NULL;
    return 0;
}

6. 打印

(1)函数定义

int print_queue(queue_t *my_queue);

(2)注意点
  1. 链式队列与顺序队列不同的一点是,链式队列的rear指向的是最后一个已存入数据的节点,顺序队列rear指向的是最后一个已存入数据的空间的下一个空间。
  2. 先打印除了最后一个节点以外所有节点,此时还有最后一个节点没打印
(3)代码实现
int print_queue(queue_t *my_queue){
    if(NULL==my_queue||NULL==my_queue->front) return -1;
    node_t *ptemp=my_queue->front;
    //打印除了最后一个节点之外所有节点
    while(ptemp!=NULL){
        printf("%d ",ptemp->data);
        ptemp=ptemp->next;
    }
    putchar(10);
    return 0;
}

四、所有源代码已上传至我的资源

下载链接:
C语言实现循环队列
C语言实现链式队列

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

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

相关文章

抖音小店三种快速出体验分的方式,看看你想要去做哪一种?

大家好,我是电商小V 很多小伙伴开的新店都是没有体验分的,大家都知道起店的第一步就是先要出分,后期的话自己店铺的体验分越高,那么店铺的权重就越大,你的商品就会进入自然流量池,那么系统给你推荐的流量就…

echarts图表英文状态下图标的横向坐标轴显示中文

解决方法: 初始化图表时传入ZH(中文)EN(英文)const locale ENinitChart() {this.chart echarts.init(this.$refs.chart, null, {locale: locale ,});this.setOptions();},

如何解决图纸加密的痛点

在当今信息高度发达的时代,图纸作为工程设计、制造、施工等领域的重要载体,其安全性显得尤为关键。然而,图纸加密却常常面临着诸多痛点,这些痛点不仅影响了企业的数据安全,也制约了行业的健康发展。 图纸加密的复杂性是…

深度解析:从概念到变革——Transformer大模型的前世今生以及大模型预备知识讲解[知存科技]

深度解析:从概念到变革——Transformer大模型的前世今生 点击:知存科技相关课程推荐 知存科技是全球领先的存内计算芯片企业。针对AI应用场景,在全球率先商业化量产基于存内计算技术的神经网络芯片。凭借颠覆性的技术创新,知存科…

微信公众号怎么做留言板功能

在繁忙的都市生活中,你是否常常感到孤单、渴望有一个可以倾诉心声的地方?今天,我要为大家介绍一个特别的角落——我们公众号的留言板功能。它不仅是一个留言板,更是一个情感交流的平台,一个可以让我们彼此心灵相通的桥…

论文阅读--GroupViT

视觉之前做无监督分割的时候,经常使用grouping方法:如果有一些聚类的中心点,从这写点开始发散,把周围相似的点逐渐扩充成一个group,这个group就相当是一个segmentation mask 右边是grouping block,左边的两…

【外汇天眼】市场如战场:交易中的攻防艺术

交易的成功如同生活,急功近利反而有害无益。在交易中,许多投资者常常面临亏损,急于挽回损失,频繁操作,结果却往往是越亏越多。交易需要耐心,不能急于一时,更不能与市场赌气。交易和生活一样&…

本周日晚8点预约宣讲会 | 深入了解项目,开启你的开源之旅!

引言 社区的亲爱的同学们!为了帮助大家在这个夏天更好的参加“开源之夏”的活动,我们联合2位资深开源项目导师,给大家策划了这次“开源之夏”宣讲会。 这不仅是一个了解如何参与开源项目的机会,更是一个直接与项目导师面对面交流…

利用显著地面特征进行配送机器人定位的鲁棒方法

论文:Salience-guided Ground Factor for Robust Localization of Delivery Robots in Complex Urban Environments 作者:Jooyong Park,Jungwoo Lee,Euncheol Choi,Younggun Cho 收录:ICRA2024 利用显著…

AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研

目录 前言一、DB-GPT总体概述二、DB-GPT关键特性1、私域问答&数据处理&RAG2、多数据源&GBI3、多模型管理4、自动化微调5、Data-Driven Multi-Agents&Plugins6、隐私安全 三、服务器资源准备1、创建实例2、打开jupyterLab 四、DB-GPT启动1、激活 conda 环境2、切…

mysql5.7允许root远程访问

mysql客户端工具配置完成后,测试联通失败,客户端真正连接mysql时,也报错不允许rootip连接。 这是由于mysql的root用户默认禁止远程访问,可以通过两种方式改表或者授权的方式开启远程访问。本文中使用改表的方法。按照如下操作即可…

如何让大模型更聪明?提升AI智能的关键策略

如何让大模型更聪明?提升AI智能的关键策略 🤖 如何让大模型更聪明?提升AI智能的关键策略摘要引言方向一:算法创新🚀1.1 自监督学习的崛起1.2 强化学习的应用 方向二:数据质量与多样性📊2.1 数据…

【EVI】Hume AI 初探

写在前面的话 Hume AI宣布已在B轮融资中筹集5000万美元,由前Google DeepMind研究员Alan Cowen创立并担任CEO。该AI模型专注于理解人类情感,并发布了「共情语音界面」演示,通过语音对话实现互动。从 Hume AI 官网展示的信息,EVI 能…

飞书API(10):通过阿里云MaxCompute数仓入库 - 转为阿里云 DataFrame 再入库

一、引入 上一小节介绍了怎么入库到阿里云的 MaxCompute 数仓,其中涉及到 2 种入库方式,一种是转为阿里云的 DataFrame,然后类似 pandas 的 DataFrame 直接写入 MySQL 的方法,将数据写入表中;另外一种是转为列表&…

【openlayers系统学习】4.3VectorTile 功能交互(指针悬停在要素上时,绘制矩形框)

三、 VectorTile 功能交互(指针悬停在要素上时,绘制矩形框) 矢量切片的好处是我们可以与要素交互,因为我们在客户端上有数据。但需要注意的一件事是矢量切片针对渲染进行了优化。这意味着要素仅包含过滤和渲染所需的属性&#xf…

如何知道huggingface/modelscope的大模型的模型层名字

下载模型后,有个文件叫model.safetensors.index.json,里面有。 你下载的大模型位置在用户名/.cache/huggingface/hub/大模型名差不多这个路径。 或者直接print(parameters.name),但是这样打出来特别多,很难看。差不多这样写&am…

Android 10.0 锁屏页面弹窗功能实现

1.前言 在10.0的系统rom产品定制化开发中,在定制化开发中,需要在锁屏页面弹窗功能,当收到某些信息的时候,需要添加 悬浮窗锁屏页面也同样需要弹窗功能,接下来就分析下相关功能,然后实现功能 2.锁屏页面弹窗功能实现的核心类 frameworks\base\core\java\android\view\Wi…

【Chrono Engine学习总结】6-创建自定义场景-6.2-chrono中的光线设置

由于Chrono的官方教程在一些细节方面解释的并不清楚,自己做了一些尝试,做学习总结。 上一篇文章中,自己【用sketchup重建了三维场景】,但导入chrono中颜色很不正确,几乎都是白色的,但也不是完全白色。经过…

2024年上半年软考什么时候查成绩?附查询流程

考试一旦结束,并不意味着与考试相关的事情也就结束了。2024年上半年信息系统项目管理师等软考考试结束后,我们还需要关注考后和证书相关的事情,比如成绩查询、证书领取等等。 2024年上半年软考成绩查询 查询时间:预计在2024年7月…

优优嗨聚集团:快速摆脱个人债务束缚的秘诀

在快节奏的现代生活中,个人债务问题时常困扰着许多人。面对日益增长的债务压力,如何快速有效地处理成为众多人的迫切需求。本文将为你提供一套实用的债务清零攻略,帮助你摆脱债务的束缚,重获财务自由。 一、认清债务现状&#xff…