数据结构(六)队列

news2024/11/17 3:45:37

文章目录

  • 一、概念
  • 二、逻辑结构:线性结构
  • 三、存储结构
    • (一)顺序队列
    • (二)循环队列
      • 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/1704939.html

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

相关文章

Solana 验证节点搭建教程 SOL节点

搭建验证节点 (成功下载快照) 部署 Solana 验证节点 由于项目需求,需要部署一台solana节点,我们从一开始搭建,遇到许多坑,做个记录。 一定要注意服务器配置,配置不够,rpc启动不起来。 一、简介 官网地址…

ChAMP加载肺癌数据和分析甲基化数据流程

ChAMP加载肺癌数据和分析甲基化数据流程 1. 加载数据分析 #!/bin/evn R rm(list = ls()) library(rstudioapi) current_script_path <- getActiveDocumentContext()$path# 将路径转换为当前目录 current_directory <- dirname(current_script_path)# 设置当前工作目录 …

代码随想录算法训练营day14|二叉树的递归遍历、二叉树的迭代遍历、二叉树的统一迭代法

二叉树的递归遍历 首先需要明确的一点是&#xff0c;前序中序和后序在二叉树的递归遍历中的区别仅在于递归函数中操作的顺序&#xff0c;前序是在遍历一个节点的左右子树前进行操作&#xff0c;中序是在遍历一个节点的左子树后进行操作再遍历右子树&#xff0c;而后序是在遍历…

【DevOps】Elasticsearch在Ubuntu 20.04上的安装与配置:详细指南

目录 一、ES 简介 1、核心概念 2、工作原理 3、 优势 二、ES 在 Ubuntu 20.04 上的安装 1、安装 Java 2、下载 ES 安装包 3、创建 ES 用户 4 、解压安装包 5、 配置 ES 6、 启动 ES 7、验证安装 三、ES 常用命令 1、创建索引 2、 插入文档 3、查询文档 四、ES…

Weblogic SSRF漏洞 [CVE-2014-4210]

漏洞复现环境搭建请参考 http://t.csdnimg.cn/svKal docker未能成功启动redis请参考 http://t.csdnimg.cn/5osP3 漏洞原理 Weblogic的uddi组件提供了从其他服务器应用获取数据的功能并且没有对目标地址做过滤和限制&#xff0c;造成了SSRF漏洞&#xff0c;利用该漏洞可以向内…

git工作流程

以财务开发为例子&#xff1a; 1. 新建分支 1.1. upstream新建分支&#xff1a;finance-feature 1.2. origin新建对应分支&#xff1a;finance-feature 1.3 新建本地分支 git branch finance-feature 注&#xff1a; 同步远程分支&#xff1a;git fetch upstream feature…

【Flutter】KeyAnimatedList组件

&#x1f525; 本文由 程序喵正在路上 原创&#xff0c;CSDN首发&#xff01; &#x1f496; 系列专栏&#xff1a;Flutter学习 &#x1f320; 首发时间&#xff1a;2024年5月28日 &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e; 目…

微软联手清华,AI注释让文本到图像生成更符合人类偏好

获取本文论文原文PDF&#xff0c;请在公众号【AI论文解读】留言&#xff1a;论文解读 摘要 本研究展示了利用人类偏好数据集来精细调整文本到图像生成模型的潜力&#xff0c;增强了生成图像与文本提示之间的一致性。尽管取得了进展&#xff0c;现有的人类偏好数据集要么构建成…

[Algorithm][动态规划][简单多状态DP问题][买卖股票的最佳时机 III][买卖股票的最佳时机 Ⅳ]详细讲解

目录 1.买卖股票的最佳时机 III1.题目链接2.算法原理详解3.代码实现 2.买卖股票的最佳时机 IV1.题目链接2.算法原理详解3.代码实现 1.买卖股票的最佳时机 III 1.题目链接 买卖股票的最佳时机 III 2.算法原理详解 注意&#xff1a;本题为了便于初始化&#xff0c;有较多细节服…

对竞品分析的理解

一、竞品分析是什么 竞品分析即对竞争对手进行分析&#xff0c;是市场研究中的一项重要工作&#xff0c;它可以帮助企业了解竞争对手的产品、策略、市场表现等信息&#xff0c;通过竞品分析可以为自己的产品制定更加精准的策略。 二、为什么要做竞品分析 1.了解市场情况 了解…

如果创办Google

本文是一篇演讲稿&#xff0c;来自于《黑客与画家》一书的作者保罗*格雷厄姆&#xff0c;被称为硅谷创业之父。这是他为14至15岁的孩子们做的一次演讲&#xff0c;内容是关于如果他们将来想创立一家创业公司&#xff0c;现在应该做些什么。很多学校认为应该向学生们传授一些有关…

【DrissionPage爬虫库 1】两种模式分别爬取Gitee开源项目

文章目录 DrissionPage爬虫库简介1. 浏览器操控模式&#xff08;类似于游戏中的后台模拟鼠标键盘&#xff09;2. 数据包收发模式&#xff08;类似于游戏中的协议封包&#xff09; 实战中学习需求&#xff1a;爬取Gitee开源项目的标题与描述解决方案1&#xff1a;用数据包方式获…

【常用的队列总结】

文章目录 队列的介绍Queue队列的基本概念与操作队列的基本概念 常见的队列介绍非阻塞队列LinkedList:ArrayDeque:PriorityQueue: 阻塞队列ArrayBlockingQueueLinkedBlockingQueuePriorityBlockingQueue DelayQueueSynchronousQueue 队列的介绍 Queue队列的基本概念与操作 在 …

Linux用docker安装ElasticsearchSpringBoot整合ES

一. 部署Elasticsearch 1. docker查询docker容器中的es docker search elasticsearch 2. 安装&#xff08;PS&#xff1a;查看自己的springBoot的版本号 对应的es版本安装&#xff09; docker pull elasticsearch:7.6.23. 查看已安装的docker镜像 docker images4. 创建挂…

【会议征稿,SPIE独立出版】第五届计算机视觉和数据挖掘国际学术会议(ICCVDM 2024)

第五届计算机视觉与数据挖掘国际学术会议&#xff08;ICCVDM 2024&#xff09;将于2024年7月19-21日在中国长春举行。此前&#xff0c;ICCVDM系列会议于2020年在中国西安、2021年在中国长沙&#xff08;线上&#xff09;、2022年在中国呼伦贝尔&#xff08;线上线下&#xff09…

【Java】JavaSE概述

1、简介 Java SE&#xff08;Java Platform, Standard Edition&#xff09;是Java技术的核心平台&#xff0c;它提供了Java编程语言、Java虚拟机&#xff08;JVM&#xff09;以及Java核心类库和API。Java SE主要用于开发和部署桌面应用程序、服务器应用程序、命令行工具和嵌入…

DBeaver怎么将编辑栏内容放大

1、窗口–》编辑器–》放大 2、ctrl 3、页面结果展示

前端大师-高级Web开发测验

目录 前言 1.按正确的执行顺序排列脚本 2.哪些说法是正确的&#xff1f;&#xff08;D&#xff09; 3.填写正确的术语 4.程序的输出 5.将资源提示与其定义匹配 6.以下程序的输出是&#xff1f; 7.将PerformanceNavigationTimings按正确的顺序排列 8.将缓存指令与其定义…

【动手学PaddleX】谁都能学会的基于迁移学习的老人摔倒目标检测

本项目使用PaddleX搭建目标检测模块&#xff0c;在一个精选的数据集上进行初步训练&#xff0c;并在另一个老年人跌倒检测的数据集上进行参数微调&#xff0c;实现了迁移学习的目标检测项目。 1.项目介绍 迁移学习是非常有用的方法&#xff0c;在实际生活中由于场景多样&…

【ai】pycharm设置软件仓库编译运行基于langchain的chatpdf

联想笔记本 y9000p创建python工程: 使用langchain支持openai的向量化embedding安装软件包 发现没有openai ,添加软件仓库打开工具窗口 点击设置