数据结构day04(队列 Queue 循环队列、链式队列)

news2024/11/27 7:26:59

目录

【1】队列 Queue

1》 队列的定义

 2》循环队列

3》链式队列 


【1】队列 Queue

1》 队列的定义

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。
队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。


队头(Front):允许删除的一端,又称队首。
队尾(Rear):允许插入的一端。
空队列:不包含任何元素的空表。

队列包括顺序队列(循环队列)、链式队列

结构先进先出FIFO

操作:创建、入列、出列、判空和判满。

注意:为了避免假溢出问题,即队列前面还有空闲,但是队尾已经出现越界,所以在实际使用队列时,为了使队列空间能重复使用,往往对队列的使用方法稍加改进,需要引入循环队列

 2》循环队列

解决假溢出的方法就是后面满了,就再从头开始,也就是头尾相接的循环。我们把队列的这种头尾相接的顺序存储结构称为循环队列。当队首指针Q->front = MAXSIZE-1后,再前进一个位置就自动到0,这可以利用除法取余运算(%)来实现。

初始时:Q->front = Q->rear=0。
队首指针进1:Q->front = (Q->front + 1) % MAXSIZE。
队尾指针进1:Q->rear = (Q->rear + 1) % MAXSIZE。
队列长度:(Q->rear - Q->front + MAXSIZE) % MAXSIZE。

出队入队时,指针都按照顺时针方向前进1,如下图所示:

 代码展示:

#include <stdio.h>
#include <stdlib.h>
#define N 10

typedef int data_t; // 重定义int类型
typedef struct queue
{
    data_t data[N]; //循环队列存数据的数组
    int front;      // 队头元素的下标
    int rear;       // 队尾元素的下标
} Que_t, *Que_p;    // 重定义队列结构体类型

/*创建空队列*/
Que_p Create()
{
    Que_p p = (Que_p)malloc(sizeof(Que_t));//开辟循环队列结构体大小空间
    if (NULL == p)//容错判断
    {
        perror("malloc lost\n");
    }
    //结构体初始化
    p->front = 0;//队头下标置0
    p->rear = 0;//队尾下标置0
    return p;//返回队列指针
}

/*判满*/
//思想上,舍去数组上的最后一个存储位置,用于判断队列是否为满,即这个位置不存数据
int Full(Que_p p)
{
    return (p->rear + 1) % N == p->front;//通过取余法,让p_rear在0-N 之间循环起来,当p_rear再次等于p_front时就是队列满的时候
}

/*入队列*/
int Push(Que_p p, int data)
{
    if (Full(p))//判满,容错判断
    {
        printf("Queue is Full\n");
        return -1;
    }
    p->data[p->rear] = data;//在队尾下标的数组位置插入要插入的数据
    p->rear = (p->rear + 1) % N;//让队尾下标再0-N 之间进行循环加一
}

/*判空*/
int Empty(Que_p p)
{
    return p->rear == p->front;//当队尾下标等于队头下标时,就像刚开辟空队列时一样,队列为空
} 

/*出队列*/
int Pop(Que_p p)
{
    if (Empty(p))//判空,容错判断
    {
        printf("Queue is Empty\n");
        return -1;
    }
    while (p->front < p->rear)
    {
        printf("%d ", p->data[p->front]);//打印队头下标的数组元素数据
        p->front = (p->front + 1) % N;//让队头下标在0-N 之间循环加一
    }
    printf("\n");
}

/*求长度*/
int Length(Que_p p)
{
    return (p->rear - p->front + N) % N;//两种情况 1.rear在front后面 长度就是rear - front
                                                 //        2.rear在front的前面  长度就是rear - front + N 
                                                 //这两种情况最终可以用(p-rear - p->front + N)% N来表示(取余法)
}

int main(int argc, char const *argv[])
{
    Que_p H = Create();//创空循环队列

    for (int i = 0; i < 9; i++)//循环调用入队列函数,入队列
    {
        Push(H, i);
    }

    printf("队列的长度: %d\n",Length(H));//调用求队列的长度函数
    printf("出队列:");
    Pop(H);//调用出队列函数 先进先出 

    return 0;
}

代码展示:

循环队列,如果数组的元素个数为N,那么队列中最多能够存储的数据数的多少? N-1个  

为什么?

答:rear 后面 队尾,在插入的时候,插入之前需要先判断 rear+1,也就是他的下一个为位置是否 等于 front 来判断队列是否为满,会造成浪费一个存储位置。

3》链式队列 

逻辑结构:线性结构

存储结构:链式存储

操作:创空、入列、出列、判空

创建空队列:

 入队:

出队:

 

 代码展示:

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

typedef struct node // 定义一个结构体,存放的是节点的数据域和指针域
{
    int data;          // 数据域
    struct node *next; // 指针域
} Node_t, *Node_p;     // 重定义结构体数据类型和指针

typedef struct link // 定义一个结构体,存放的是指向队头和队尾的node结构体指针
{
    Node_p front;  // 队头指针
    Node_p rear;   // 队尾指针
} Link_t, *Link_p; // 重定义

/*创建空的队列,并创建一个指针结构体指向队列的头*/
Link_p Create()
{
    Link_p p = (Link_p)malloc(sizeof(Link_t)); // 开辟堆区空间存放一个存放指针的结构体,让该指针类型的指针接受该内存空间
    if (NULL == p)                             // 容错判断
    {
        printf("malloc lost\n");
        return NULL;
    }
    p->front = p->rear = (Node_p)malloc(sizeof(Node_t)); // 让上一个结构体内的两个指针都指向开辟的一个存放节点的堆区空间
    if (NULL == p->front)                                // 容错判断
    {
        printf("malloc lost\n");
        return NULL;
    }
    p->front->next = NULL; // 通过存放指针的结构体找到节点的指针域next,并初始化为NULL
    return p;
}

/*入队列*/
int Push(Link_p p, int data)
{
    Node_p p_new = (Node_p)malloc(sizeof(Node_t)); // 让一个新的node类型的指针指向开辟的新的节点堆区空间
    if (NULL == p_new)                             // 容错判断
    {
        printf("malloc lost\n");
        return -1;
    }
    p_new->data = data; // 新节点数据域初始化
    p_new->next = NULL; // 新节点指针域初始化

    p->rear->next = p_new; // 将新节点链接到队列中
    p->rear = p_new;       // 让队尾移动到新节点位置
}

/*判空*/
int Empty(Link_p p)
{
    return p->front == p->rear; // 当队头和队尾重合时 说明队列是空的
}

/*出队列*/
int Pop(Link_p p)
{
    if (Empty(p)) // 判空
    {
        printf("queue is Empty\n");
        return -1;
    }
    while (p->front < p->rear) // 当队头没到达队尾的位置,就进入循环
    {
        Node_p p_del = NULL;           // 定义一个指针p_del,初始化为NULL
        p_del = p->front;              // 让该指针指向队头
        p->front = p->front->next;     // 队头往后移动
        printf("%d ", p->front->data); // 打印当前队头的数据
        free(p_del);                   // 释放掉怕p_del所指的节点
        p_del = NULL;                  // 置空,以防野指针
    }
}

/*队列的长度*/
int Length(Link_p p)
{
    int len = 0;//定义一个变量保存队列长度
    Node_p q = p->front->next;//定义一个结构体指针,指向头节点的下一个节点
    while (q != NULL)//当q不为NULL,进入循环
    {
        len++;//队列长度加一
        q = q->next;//q指针指向下一个节点
    }
    return len;//返回队列长度
}
int main(int argc, char const *argv[])
{
    Link_p H = Create();        // 创建一个空结构体
    for (int i = 0; i < 6; i++) // 循环调用入队列函数
        Push(H, i);
    printf("队列的长度: %d\n", Length(H));
    printf("出队列: ");
    Pop(H); // 调用出队列函数  队列:先入先出
    printf("\n");
    return 0;
}

运行结果:


 今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话请给个三连支持一下吧!

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

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

相关文章

Day23 第十站 文件IO的多路复用

#include <myhead.h>void insert_client(int *client_arr,int *len,int client) {//client_arr[n]{3,4} len&client_count,client_count2;//添加 5 client_arr[2(*len)]5(client)client_arr[*len]client;(*len); } int find_client(int *client_arr,int len,int clie…

Spring DI 数据类型—— set 方法注入

首先新建项目&#xff0c;可参考 初识IDEA、模拟三层--控制层、业务层和数据访问层 一、spring 环境搭建 &#xff08;一&#xff09;pom.xml 导相关坐标 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.or…

代码随想录算法训练营第二十二天| 77. 组合 216.组合总和III 17.电话号码的字母组合

77. 组合 题目&#xff1a; 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],[1,3],[1,4], ] 示例 2&#xff1a…

VAuditDemo安装漏洞

目录 VAuditDemo安装漏洞 index.php header.php config.php lib.php install.php 分析结果 漏洞利用 第一步&#xff1a;删除install.lock文件&#xff0c;访问 install.php 抓包 第二步&#xff1a;通过审计构造payload 第三步&#xff1a;修改抓包请求内容&#x…

客户分级管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图详细视频演示为什么选择我官方认证闲鱼玩家&#xff0c;服务很多代码文档&#xff0c;百分百好评&#xff0c;战绩可查&#xff01;&#xff01;入职于互联网大厂&#xff0c;可以交流&#xff0c;共同进步。有保障的售后 代码参考数据库参考源码获取…

《python语言程序设计》2018版第7章第10题设计一个名为time的类,包括hour minute second

#main代码段 def main():a int(time.time())total_second int(a)current_second total_second % 60total_minutes total_second // 60current_minute total_minutes % 60total_hours total_minutes // 60current_hour total_hours % 24b exCode07.Time(current_hour,cu…

SpringBoot中生成二维码的案例实战

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

基于数据复杂度的数据库选型

数据模型的选择对于 IT 系统的开发至关重要&#xff0c;它不仅决定了数据存储和处理的方式&#xff0c;影响系统的性能、扩展性以及维护性等。本质上来说&#xff0c;不同的数据模型反映了我们对业务问题的不同思考和抽象程度。 今天我们从不同数据模型对于复杂数据和关系的支…

定制化三防平板:为专业领域打造的坚固解决方案

在科技时代&#xff0c;移动设备已经成为各行各业不可或缺的工具。然而&#xff0c;对于一些特殊行业&#xff0c;如军事、野外勘探、物流、医疗和制造业等&#xff0c;普通商用平板往往无法满足其严苛的工作环境需求。三防平板&#xff0c;以其卓越的防护性能和高度的定制化能…

有了这4款工具,你就知道电脑怎么录屏了!

电脑屏幕录屏这个问题很多人都会碰到&#xff0c;比如教学视频录制&#xff0c;游戏技巧分享&#xff0c;软件操作演示等等。因为场景众多&#xff0c;电脑自带的录屏功能不一定能满足&#xff0c;所以借助第三方工具是一个很有效的办法。如果大家不知道如何录屏&#xff0c;可…

网络安全-安全策略初认识

文章目录 前言理论介绍1. 安全策略1.1 定义&#xff1a;1.2 关键术语&#xff1a; 2. 防火墙状态监测 实战步骤1&#xff1a;实验环境搭建步骤2&#xff1a;配置实现 总结1. 默认安全策略2. 自定义安全策略3. 防火墙状态会话表 前言 who&#xff1a;本文主要写给入门防火墙的技…

【Vue3】集成 Ant Design Vue

【Vue3】集成 Ant Design Vue 背景简介开发环境开发步骤及源码总结 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努力学习奋斗…

SX_gitlab可视化操作c语言知识_17

gitlab可视化操作技巧: Merge into current branch直接将远程wjc_GNSS分支的数据拉下来同步到本机当前的分支代码&#xff0c;执行的是合并操作&#xff0c;即多的模块会添加到本地分支&#xff0c;有冲突的地方不行得rebase覆盖才行 修改完代码先暂存更改再在暂存区写入备注&a…

特斯拉FSD硬件进化

特斯拉FSD硬件进化 历经十年&#xff0c;特斯拉自动驾驶软硬件系统不断进化。硬件&#xff1a;HW1.0 到 HW4.0&#xff0c;自研比例与配置性能不断提升。 2013 年&#xff0c;马斯克于推特披露特斯拉正在进行辅助驾驶系统 AP&#xff08;Autopilot System&#xff09;的研发&…

鸿蒙(API 12 Beta3版)【使用ImageSource完成图片解码】图片开发指导

图片解码指将所支持格式的存档图片解码成统一的[PixelMap]&#xff0c;以便在应用或系统中进行图片显示或[图片处理]。当前支持的存档图片格式包括JPEG、PNG、GIF、WebP、BMP、SVG、ICO、DNG。 开发步骤 全局导入Image模块。 import { image } from kit.ImageKit;获取图片。…

Compose知识分享

前言 “Jetpack Compose 是一个适用于 Android 的新式声明性界面工具包。Compose 提供声明性 API&#xff0c;让您可在不以命令方式改变前端视图的情况下呈现应用界面&#xff0c;从而使编写和维护应用界面变得更加容易。” 以上是Compose官网中对于Compose这套全新的Androi…

MidJourney付费失败的原因以及失败后如何取消或续订(文末附MidJourney,GPT-4o教程)

MidJourney付费失败的原因 MidJourney付费失败的原因可能包括支付方式无效、支付信息错误、网络问题、账户设置问题等。 ‌支付方式无效或信息错误‌&#xff1a;如果用户提供的支付方式&#xff08;如信用卡&#xff09;信息不正确&#xff0c;或者支付方式本身不支持该地区…

Python使用matplotlib计算并绘制图像的直方图

除了使用OpenCV计算图像直方图外&#xff0c;matplotlib也提供了直方图计算并绘制功能&#xff0c;只需要把图像&#xff08;或对应通道&#xff09;作为参数输入&#xff0c;即可通过matplotlib输出直方图&#xff08;标准直方图&#xff0c;非条形图表达&#xff09;&#xf…

LVS负载均衡群集-DR模式

一、负载均衡群集 1.数据包流向分析 客户端发送请求到 Director Server&#xff08;负载均衡器&#xff09;&#xff0c;请求的数据报文&#xff08;源 IP 是 CIP,目标 IP 是 VIP&#xff09;到达内核空间。Director Server 和 Real Server 在同一个网络中&#xff0c;数据通过…

MKS MWH-5匹配器Automatc matching impedance Network手侧

MKS MWH-5匹配器Automatc matching impedance Network手侧