【数据结构】队列——顺序实现+链式实现(带头结点+不带头结点)入队 出队 初始化 判空 双端队列 完整代码

文章目录

  • 四 队列
    • 1.基本概念
    • 2.队列的顺序存储
    • 3.队列的链式实现
      • 3.1 定义
      • 3.2 带头结点
        • 3.2.1 初始化
        • 3.2.2 判空
        • 3.2.3 入队
        • 3.2.4 出队
        • 3.2.5 完整代码
      • 3.3 不带头结点
        • 3.3.1 初始化
        • 3.3.2 入队
        • 3.3.3 出队
        • 3.3.4 完整代码
    • 4.双端队列

四 队列

1.基本概念

  • 定义

    只允许在一端进行插入,在另一端删除的线性表。

  • 术语

    • 队头:允许删除的一端。
    • 队尾:允许插入的一端。
  • 特点:先进先出

2.队列的顺序存储

  • 定义

    #define MaxSize 10
    #define ElemType int
    //定义
    typedef struct {ElemType data[MaxSize];//用静态数组存放队列元素int front, rear;//队头指针和队尾指针
    }SqQueue;
    
  • 循环队列

    搞成循环队列可以节约存储空间。

    避免出现队尾指针Q.rear已经到MaxSize时,队头指针Q.front前有剩余空间的情况。

  • 在循环队列下,队列空的条件是

    Q.rear==Q.front

  • 在循环队列下,队列已满的条件是

    (Q.rear+1)%MaxSize==Q.front

    即尾指针加一等于头指针时,队列已满。

    注:此时会浪费一个存储空间(队尾指针没有存数据)。

    • 如果不浪费,即尾指针rear也存元素,则队满和队空判断条件相同,我们无法用逻辑表达区分两种情况。

  • 如果题目要求不能浪费一点点存储空间,则将队列定义为

    typedef struct {ElemType data[MaxSize];//用静态数组存放队列元素int front, rear;//队头指针和队尾指针int size;//队列大小
    }SqQueue;
    
    • 此时队满条件:size==MaxSize
    • 队空条件:size==0
  • 完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define MaxSize 10
#define ElemType int//定义
typedef struct {ElemType data[MaxSize];//用静态数组存放队列元素int front, rear;//队头指针和队尾指针
}SqQueue;//初始化队列
void InitQueue(SqQueue& Q)
{//初始时,队头队尾指针都指向0Q.front = Q.rear = 0;
}//判空
bool QueueEmpty(SqQueue Q)
{if (Q.rear == Q.front)return true;elsereturn false;
}//创建
bool CreatQueue(SqQueue& Q)
{int n = 5;srand(time(0));while (n--){//队满则报错//队满条件:队尾指针的下一个位置是队头if ((Q.rear + 1) % MaxSize == Q.front)return false;Q.data[Q.rear] = rand() % 100 + 1;//新元素插入队尾//将存储空间在逻辑上变成环状(循环队列)Q.rear = (Q.rear + 1) % MaxSize;//队尾指针加1取模}return true;
}//入队
bool EnQueue(SqQueue& Q, ElemType x)
{//队满则报错//队满条件:队尾指针的下一个位置是队头if ((Q.rear + 1) % MaxSize == Q.front)return false;Q.data[Q.rear] = x;//新元素插入队尾//将存储空间在逻辑上变成环状(循环队列)Q.rear = (Q.rear + 1) % MaxSize;//队尾指针加1取模return true;
}//出队
bool DeQueue(SqQueue& Q, ElemType& x)
{//判空if (Q.rear == Q.front)return false;x = Q.data[Q.front];//x存出队的元素Q.front = (Q.front + 1) % MaxSize;//头指针后移return true;
}//获取队头元素,用x返回
bool GetHead(SqQueue Q, ElemType& x)
{if (Q.rear == Q.front)return false;x = Q.data[Q.front];return true;
}void QPrint(SqQueue Q) 
{for (int i = Q.front; i < Q.rear-1; i=(i+1) % MaxSize){printf("%d,", Q.data[i]);}printf("%d\n", Q.data[Q.rear-1]);
}int main()
{SqQueue Q;InitQueue(Q);printf("创建:\n");CreatQueue(Q);QPrint(Q);printf("\n");printf("请输入入队元素:\n");int x;scanf_s("%d", &x);EnQueue(Q, x);QPrint(Q);printf("\n");int y;DeQueue(Q, y);printf("出队元素:%d\n", y);QPrint(Q);printf("\n");int z;GetHead(Q, z);printf("队头元素:%d\n", z);
}

3.队列的链式实现

3.1 定义

分两个结构体

1.节点结构体:存节点数据和下一个节点地址。

2.队列结构体:存队列的头尾指针。

//定义
//链式队列节点
typedef struct LinkNode {ElemType data;struct LinkNode* next;
}LinkNode;
//链式队列
typedef struct {LinkNode* front;//指向队列队头的指针LinkNode* rear;//指向队列队尾的指针
}LinkQueue;
  • 可分为带头结点和不带头结点,两者功能差不多,具体看题目要求选哪个。
  • 因为是链表,所以不存在队满的时候,也不需要用循环队列。

3.2 带头结点

3.2.1 初始化

1.创建一个头节点;

2.将头尾指针front和rear都指向头节点;

3.头节点的next赋空值NULL。

//初始化队列
void InitQueue(LinkQueue& Q)
{//初始时 front、rear都指向头结点Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));Q.front->next = NULL;
}

3.2.2 判空

当头尾指针都指向同一节点时,链表为空。

//判空
bool IsEmpty(LinkQueue& Q)
{if (Q.front == Q.rear)return true;elsereturn false;
}

3.2.3 入队

  • 步骤

    1.创建新节点,存数据+初始化指针域。

    2.新节点插入到原rear之后。

    3.更新rear,即使尾结点指向新插入节点。

void EnQueue(LinkQueue& Q, ElemType x)
{LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = x;s->next = NULL;Q.rear->next = s;//新节点插入到rear之后Q.rear = s;//修改表尾指针
}

3.2.4 出队

根据队列中是否只有一个结点分两种情况。

  • 有多个结点时

    1.头结点和出队结点的下一个结点相连。

    2.释放出队结点。

  • 只有一个结点时

    1.尾结点指向头结点。

    2.释放出队结点。

    • 此时相当于空队列。

bool DeQueue(LinkQueue& Q, ElemType& x)
{//空队if (Q.front == Q.rear)return false;LinkNode* p = Q.front->next;x = p->data;//用变量x返回队头元素Q.front->next = p->next;//修改头指针的next指针,即连上出队节点的下一个节点//如果出队节点是尾节点,即队列中只有一个节点if (Q.rear == p)Q.rear = Q.front;//变成空队列free(p);//释放出队节点return true;
}

3.2.5 完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ElemType int//定义
//链式队列节点
typedef struct LinkNode {ElemType data;struct LinkNode* next;
}LinkNode;
//链式队列
typedef struct {LinkNode* front;//指向队列队头的指针LinkNode* rear;//指向队列队尾的指针
}LinkQueue;//初始化队列
void InitQueue(LinkQueue& Q)
{//初始时 front、rear都指向头结点Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode));Q.front->next = NULL;
}//判空
bool IsEmpty(LinkQueue& Q)
{if (Q.front == Q.rear)return true;elsereturn false;
}//创建
bool CreatQueue(LinkQueue& Q)
{int n = 5;srand(time(0));while (n--){LinkNode* t = (LinkNode*)malloc(sizeof(LinkNode));t->data = rand() % 100 + 1;t->next = NULL;Q.rear->next = t;Q.rear = t;}return true;
}//新元素入队
void EnQueue(LinkQueue& Q, ElemType x)
{LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = x;s->next = NULL;Q.rear->next = s;//新节点插入到rear之后Q.rear = s;//修改表尾指针
}//出队
//用x返回元素
bool DeQueue(LinkQueue& Q, ElemType& x)
{//空队if (Q.front == Q.rear)return false;LinkNode* p = Q.front->next;x = p->data;//用变量x返回队头元素Q.front->next = p->next;//修改头指针的next指针,即连上出队节点的下一个节点//如果出队节点是尾节点,即队列中只有一个节点if (Q.rear == p)Q.rear = Q.front;//变成空队列free(p);//释放出队节点return true;
}void QPrint(LinkQueue&Q)
{LinkNode* p = Q.front->next;while (p != Q.rear){printf("%d ", p->data);p = p->next;}printf("%d\n\n", Q.rear->data);
}int main()
{LinkQueue Q;InitQueue(Q);CreatQueue(Q);QPrint(Q);printf("请输入要入队的元素:\n");int x;scanf_s("%d", &x);EnQueue(Q, x);QPrint(Q);int y;DeQueue(Q, y);printf("出队元素为:%d\n", y);QPrint(Q);
}

3.3 不带头结点

3.3.1 初始化

//初始化队列
void InitQueue(LinkQueue& Q)
{//初始时 front、rear都指向NULLQ.front = NULL;Q.rear = NULL;
}

3.3.2 入队

根据入队元素是否是队列中第一个结点分两种情况。

  • 如果入队结点是第一个结点

    则头尾指针都指向入队结点。

  • 如果不是

    则新结点插入到队尾结点之后,并更新队尾结点

void EnQueue(LinkQueue& Q, ElemType x)
{LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = x;s->next = NULL;//在空队列中插入第一个元素if (Q.front == NULL){Q.front = s;//队头队尾指针都指向第一个元素Q.rear = s;}else{Q.rear->next = s;//新节点插入到队尾节点之后Q.rear = s;//更新队尾节点}
}

3.3.3 出队

  • 如果是最后一个结点出队,则需要恢复成空队状态。
bool DeQueue(LinkQueue& Q, ElemType& x)
{//空队if (Q.front == NULL)return false;LinkNode* p = Q.front;//p指向此次出队的节点x = p->data;//用变量x返回队头元素Q.front = p->next;//头指针指向出队节点的下一个节点//如果是最后一个节点出队//恢复成空队状态if (Q.rear == p){Q.front = NULL;//front指向NULLQ.rear = NULL;//rear指向NULL}free(p);//释放节点空间return true;
}

3.3.4 完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>#define ElemType int//定义
//链式队列节点
typedef struct LinkNode {ElemType data;struct LinkNode* next;
}LinkNode;
//链式队列
typedef struct {LinkNode* front;//指向队列队头的指针LinkNode* rear;//指向队列队尾的指针
}LinkQueue;//初始化队列
void InitQueue(LinkQueue& Q)
{//初始时 front、rear都指向NULLQ.front = NULL;Q.rear = NULL;
}
//判空
bool IsEmpty(LinkQueue& Q)
{if (Q.front == NULL)return true;elsereturn false;
}//创建
bool CreatQueue(LinkQueue& Q)
{int n = 5;srand(time(0));while (n--){LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = rand() % 100 + 1;s->next = NULL;//在空队列中插入第一个元素if (Q.front == NULL){Q.front = s;//队头队尾指针都指向第一个元素Q.rear = s;}else{Q.rear->next = s;//新节点插入到队尾节点之后Q.rear = s;//更新队尾节点}}return true;
}//入队
void EnQueue(LinkQueue& Q, ElemType x)
{LinkNode* s = (LinkNode*)malloc(sizeof(LinkNode));s->data = x;s->next = NULL;//在空队列中插入第一个元素if (Q.front == NULL){Q.front = s;//队头队尾指针都指向第一个元素Q.rear = s;}else{Q.rear->next = s;//新节点插入到队尾节点之后Q.rear = s;//更新队尾节点}
}//出队
bool DeQueue(LinkQueue& Q, ElemType& x)
{//空队if (Q.front == NULL)return false;LinkNode* p = Q.front;//p指向此次出队的节点x = p->data;//用变量x返回队头元素Q.front = p->next;//头指针指向出队节点的下一个节点//如果是最后一个节点出队//恢复成空队状态if (Q.rear == p){Q.front = NULL;//front指向NULLQ.rear = NULL;//rear指向NULL}free(p);//释放节点空间return true;
}void QPrint(LinkQueue& Q)
{LinkNode* p = Q.front;while (p != Q.rear){printf("%d ", p->data);p = p->next;}printf("%d\n\n", Q.rear->data);
}int main()
{printf("不带头节点:\n");LinkQueue Q;InitQueue(Q);CreatQueue(Q);QPrint(Q);printf("请输入要入队的元素:\n");int x;scanf_s("%d", &x);EnQueue(Q, x);QPrint(Q);int y;DeQueue(Q, y);printf("出队元素为:%d\n", y);QPrint(Q);
}

4.双端队列

  • 定义

    允许从两端插入删除的线性表。

  • 衍生

    • 输出受限的双端队列

      只允许从一端插入,两端删除。

    • 输出受限的双端队列

      只允许从两端插入,一端删除。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于人工智能与边缘计算Aidlux的鸟类检测驱赶系统(可修改为coco 80类目标检测)

●项目名称 基于人工智能与边缘计算Aidlux的鸟类检测驱赶系统&#xff08;可修改为coco 80类目标检测&#xff09; ●项目简介 本项目在Aidlux上部署鸟类检测驱赶系统&#xff0c;通过视觉技术检测到有鸟类时&#xff0c;会进行提示。并可在源码上修改coco 80类目标检测索引直…

Kotlin Jetpack Compose - 实现Tab布局

Tab布局是一种常见的UI设计&#xff0c;它允许用户在不同的视图或数据集之间切换。我们将使用Jetpack Compose的 TabRow 和 ScrollableTabRow 组件来实现这个布局。 一、基本的Tab布局——TabRow 二、滚动的Tab布局——ScrollableTabRow 组件 三、自定义Tab组件 一、基本的T…

appium如何连接多台设备

目录 前言&#xff1a; 1.我们拿两台设备来模拟操作下&#xff0c;使用&#xff1a;adb devices查看连接状况&#xff0c;获取到设备名称。 2.获取需要操作app的包名和页面名称&#xff08;前提该设备已经打开了app&#xff09; 3.设置初始配置信息 4.打开页面后操作元素&am…

Spring MVC相关注解运用 —— 上篇

目录 一、Controller、RequestMapping 1.1 示例程序 1.2 测试结果 二、RequestParam 2.1 示例程序 2.2 测试结果 三、RequestHeader、CookieValue 3.1 示例程序 3.2 测试结果 四、SessionAttributes 4.1 示例程序 4.2 测试结果 五、ModelAttribute 5.1 示例程序 …

A核与M核异构通信过程解析

现在越来越多的产品具有M core和A core的异构架构&#xff0c;既能达到M核的实时要求&#xff0c;又能满足A核的生态和算力。比如NXP的i.MX8系列、瑞萨的RZ/G2L系列以及TI的AM62x系列等等。虽然这些处理器的品牌及性能有所不同&#xff0c;但多核通信原理基本一致&#xff0c;都…

Spring Boot中的SimpMessagingTemplate是什么,原理,以及如何使用

Spring Boot中的SimpMessagingTemplate是什么&#xff0c;原理&#xff0c;以及如何使用 SimpMessagingTemplate是Spring Framework中的一个类&#xff0c;用于向WebSocket客户端发送消息。在Spring Boot应用程序中&#xff0c;可以使用SimpMessagingTemplate来实现WebSocket通…

OpenCV 学习笔记(C++)(1.4W字)

一切图像皆Mat OpenCV中图像对象的创建与复制 Mat基本结构 Mat对象数据组成&#xff1a;头部和数据部分&#xff0c;头部存储图像的属性&#xff08;大小、宽高、图像类型&#xff1a;浮点数类型、字节类型、16位整型、32位整型、双精度浮点型&#xff0c;通道数量和获取途径…

【微服务】什么是微服务?-- 全面了解微服务架构

What is Microservices — Edureka 您有没有想过&#xff0c;什么是微服务以及扩展行业如何与它们集成&#xff0c;同时构建应用程序以满足客户的期望&#xff1f; 要了解什么是微服务&#xff0c;您必须了解如何将单体应用程序分解为独立打包和部署的小型微型应用程序。本文将…

在windows server上用Mosquitto软件创建MQTT服务器

今天下午捣鼓了半天&#xff0c;在云服务器上面创建了个MQTT服务器&#xff0c;然后用MQTTX软件进行了测试。过程记录如下&#xff1a; 1、下载mosquitto软件&#xff0c;链接如下图&#xff1a; 2、下载完成后安装&#xff0c;一直点下一步下一步就好了。 3、在安装路径下&am…

CHATGPT使用笔记

CHATGPT是帮你做事&#xff0c;而不是替你做事 1、联网插件&#xff1a; 使用Webpilot插件联网时还可以同时使用其它两种插件&#xff08;一次可以同时使用三个插件&#xff09;&#xff0c;而使用Web Browsing插件功能联网时无法使用插件功能&#xff08;联网功能和插件只能…

Celery分布式异步框架

Celery异步任务框架 """ 1&#xff09;可以不依赖任何服务器&#xff0c;通过自身命令&#xff0c;启动服务(内部支持socket) 2&#xff09;celery服务为为其他项目服务提供异步解决任务需求的 注&#xff1a;会有两个服务同时运行&#xff0c;一个是项目服务&a…

基于SpringCloud微服务流动资金贷款业务系统设计与实现

一、引言 由于传统的贷款业务系统并不能够顺应时代的变化,同时在一定程度上对业务发展进行了限制,所以为了适应时代的发展,信息贷款业务应该能够被产品化、丰富化,同时还需要制定一套特定的流程来满足新时代用户的需求。流程化的规范管理是当今银行业务发展的必然趋势,研究并开…