目录

一、队列的定义

二、循环队列

1、 循环队列的储存结构

2、初始化

3、输出队列元素

4、入队

5、出队

6、取队头元素

7、求队列长度

8、源代码

三、链式队列

1、队列的链式存储结构表示

2、初始化

3.输出队列元素

4.入队

5.出队

6.取队头元素

7. 源代码

总结


一、队列的定义

队列(Queue)是一种先进先出(FIFO,First-In-First-Out)的线性表。

在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为 rear)进行插入操作,在前端(称为 front)进行删除操作。这和日常生活中的排队时一致的,最早进入队列的元素最早离开。

常见队列有三种:循环队列、链式队列、双端队列。

双端队列又名double ended queue,简称deque,是队列的一种变形,双端队列没有队列和栈这样的限制级,它允许两端进行入队和出队操作,也就是说元素可以从队头出队和入队,也可以从队尾出队和入队

队列基本操作有:

  • 初始化队列:InitQueue(Q)
  • 判断队列是否为空:IsEmpty(Q)
  • 判断队列是否已满:IsFull(Q)
  • 入队操作:EnterQueue(Q,data)
  • 出队操作:DeleteQueue(Q,&data)
  • 取队首元素:GetHead(Q,&data)
  • 清空队列:ClearQueue(&Q)

二、循环队列

循环队列其实就是将数组的首尾相连,组成的一个特殊结构。头、尾指针以及队列元素之间的关系不变,只是在循环队列中,头、尾指针“依环状增1"的操作可用“模”运算来实现。通过取模,头指针和尾指针就可以在顺序表空间内以头尾衔接的方式“循环”移动。

1、 循环队列的储存结构

typedef struct {int* base;//储存空间的基地址int front;//头指针int rear;//尾指针int maxsize;//队列最大长度
}SqQueue;

2、初始化

动态分配一个大小为size的数组空间,base指向数组空间首地址。

SqQueue* InitQueue(int size) {SqQueue* Q = malloc(sizeof(SqQueue));//先创建队列结构体指针Q->base = (int*)malloc(sizeof(int) * size);//为队列分配一个最大容量为size的数组空间//队列最大长度置为size,头指针尾指针置为0,队列为空Q->maxsize = size;Q->front = 0;Q->rear = 0;return Q;
}

3、输出队列元素

void print(SqQueue* Q) {printf("(front) ");int i;//跟遍历数组差不多,就是要通过模运算防止越界for (i = Q->front; i != Q->rear; i = (i + 1) % Q->maxsize) {printf("%d ", Q->base[i]);}printf("(rear)\n");
}

4、入队

入队指在队尾插入一个新元素。

bool EnQueue(SqQueue* Q, int e) {//插入e作为新队尾元素if ((Q->rear + 1) % Q->maxsize == Q->front) return false;//尾指针在循环意义上加1后等于头指针说明队满Q->base[Q->rear] = e;//将元素e插入队尾Q->rear = (Q->rear + 1) % Q->maxsize;//尾指针加1return true;
}

示例

初始化一个最大长度为5的队列,用循环将四个元素入队 ,最后输出。

5、出队

出队指将队头元素删除

bool DeQueue(SqQueue* Q, int* e) {//删除队头元素,用e返回其值if (Q->front == Q->rear) return false;//队空*e = Q->base[Q->front];//用e保存队头元素Q->front = (Q->front + 1) % Q->maxsize;//头指针加1return true;
}

示例

接着入队示例,出队三个元素,再入队两个元素,最后输出。

6、取队头元素

bool GetHead(SqQueue* Q, int* e) {//返回队头元素,不修改头指针if (Q->front == Q->rear) return false;//队空*e = Q->base[Q->front];return true;
}

7、求队列长度

对于非循环队列,尾指针与头指针的差值就是队列长度;但是循环队列差值可能为负数,所以需要将差值加上maxsize再与maxsize求余。

int QueueLength(SqQueue* Q) {//返回队列元素个数return (Q->rear - Q->front + Q->maxsize) % Q->maxsize;
}

8、源代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct {int* base;//储存空间的基地址int front;//头指针int rear;//尾指针int maxsize;//队列最大长度
}SqQueue;
//初始化
SqQueue* InitQueue(int size) {SqQueue* Q = malloc(sizeof(SqQueue));//先创建队列结构体指针Q->base = (int*)malloc(sizeof(int) * size);//为队列分配一个最大容量为size的数组空间//队列最大长度置为size,头指针尾指针置为0,队列为空Q->maxsize = size;Q->front = 0;Q->rear = 0;return Q;
}
//输出
void print(SqQueue* Q) {printf("(front) ");int i;//跟遍历数组差不多,就是要通过模运算防止越界for (i = Q->front; i != Q->rear; i = (i + 1) % Q->maxsize) {printf("%d ", Q->base[i]);}printf("(rear)\n");
}
//入队
bool EnQueue(SqQueue* Q, int e) {//插入e作为新队尾元素if ((Q->rear + 1) % Q->maxsize == Q->front)    return false;//尾指针在循环意义上加1后等于头指针说明队满Q->base[Q->rear] = e;//将元素e插入队尾Q->rear = (Q->rear + 1) % Q->maxsize;//尾指针加1return true;
}
//出队
bool DeQueue(SqQueue* Q, int* e) {//删除队头元素,用e返回其值if (Q->front == Q->rear)    return false;//队空*e = Q->base[Q->front];//用e保存队头元素Q->front = (Q->front + 1) % Q->maxsize;//头指针加1return true;
}
//取队头元素
bool GetHead(SqQueue* Q, int* e) {//返回队头元素,不修改头指针if (Q->front == Q->rear)    return false;//队空*e = Q->base[Q->front];return true;
}
//求队列长度
int QueueLength(SqQueue* Q) {//返回队列元素个数return (Q->rear - Q->front + Q->maxsize) % Q->maxsize;
}
int main() {int i, n, e;SqQueue* Q = InitQueue(5);for (scanf("%d", &n), i = 0; i < n; i++) {scanf("%d", &e);EnQueue(Q, e);}print(Q);DeQueue(Q, &e);printf("e=%d\n", e);DeQueue(Q, &e);printf("e=%d\n", e);DeQueue(Q, &e);printf("e=%d\n", e);for (scanf("%d", &n), i = 0; i < n; i++) {scanf("%d", &e);EnQueue(Q, e);}print(Q);
}

三、链式队列

链队列是指采用链式存储结构实现的队列。通常链队列用单链表来表示。一个链队列显然需要两个分别指示队头和队尾的指针(分别称为头指针和尾指针)才能唯一确定。这里和线性表的单链表一样,为了操作方便起见,给链队列添加一个头结点,并令头指针始终指向头结点。

当然也有用单向循环链表表示的队列,与单链表不同的是尾节点指向了头结点,所以只需

一个指针指向尾结点就可以实现基本操作。

1、队列的链式存储结构表示

typedef struct {int data;struct QNode* next;
}QNode;
typedef struct {QNode* front;//队头指针QNode* rear;//队尾指针
}LinkQueue;

2、初始化

链队的初始化操作就是构造一个只有一个头结点的空队。

LinkQueue* InitQueue() {LinkQueue* Q = malloc(sizeof(LinkQueue));//生成队头队尾指针Q->front = (QNode*)malloc(sizeof(QNode));//生成新结点作为头结点,队头队尾指针指向该结点Q->rear = Q->front;Q->front->next = NULL;//头结点指针域置空return Q;
}

3.输出队列元素

跟遍历链表一样,就是要判断队是否为空。

void print(LinkQueue *Q) {//前提为队不为空printf("(front) ");if (Q->front != Q->rear) {QNode* p = Q->front->next;while (p != NULL) {printf("%d ", p->data);p = p->next;}}printf("(rear)\n");
}

4.入队

链队入队不需要判断队满,只需为入队元素动态分配一个结点空间。

void EnQueue(LinkQueue* Q, int e) {QNode* p = malloc(sizeof(QNode));//生成新结点p->data = e;//新结点数据域置为e,指针域置空p->next = NULL;Q->rear->next = p;//新结点插入队尾Q->rear = p;//修改队尾指针
}

示例

用循环将5个元素入队,最后输出队列。

运行结果如下

5.出队

需要判断队是否为空,出队后可释放队头元素空间。

bool DeQueue(LinkQueue* Q, int* e) {//删除队头元素,用e返回其值if (Q->front == Q->rear)   return false;//判断队列是否为空QNode* p = Q->front->next;//p指向队头元素*e = p->data;//e保存队头元素Q->front->next = p->next;//修改头结点指针域if (Q->rear == p)  Q->rear = Q->front;//最后一个元素被删,队尾指针指向头结点free(p);//释放队头元素空间return true;
}

示例

接着入队示例,出队一个元素并输出,最后输出队列

运行结果如下

6.取队头元素

bool GetHead(LinkQueue* Q, int* e) {//返回队头元素,不修改队头指针if (Q->front == Q->rear)  return false;//判断队列是否为空QNode* p = Q->front->next;*e =p->data;//用e返回队头元素值return true;
}

7. 源代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct {int data;struct QNode* next;
}QNode;
typedef struct {QNode* front;//队头指针QNode* rear;//队尾指针
}LinkQueue;
//初始化
LinkQueue* InitQueue() {LinkQueue* Q = malloc(sizeof(LinkQueue));//生成队头队尾指针Q->front = (QNode*)malloc(sizeof(QNode));//生成新结点作为头结点,队头队尾指针指向该结点Q->rear = Q->front;Q->front->next = NULL;//头结点指针域置空return Q;
}
//入队
void EnQueue(LinkQueue* Q, int e) {QNode* p = malloc(sizeof(QNode));//生成新结点p->data = e;//新结点数据域置为e,指针域置空p->next = NULL;Q->rear->next = p;//新结点插入队尾Q->rear = p;//修改队尾指针
}
//出队
bool DeQueue(LinkQueue* Q, int* e) {//删除队头元素,用e返回其值if (Q->front == Q->rear)  return false;//判断队列是否为空QNode* p = Q->front->next;//p指向队头元素*e = p->data;//e保存队头元素Q->front->next = p->next;//修改头结点指针域if (Q->rear == p)  Q->rear = Q->front;//最后一个元素被删,队尾指针指向头结点free(p);//释放队头元素空间return true;
}
//取队头元素
bool GetHead(LinkQueue* Q, int* e) {//返回队头元素,不修改队头指针if (Q->front == Q->rear) return false;//判断队列是否为空QNode* p = Q->front->next;*e = p->data;//用e返回队头元素值return true;
}
//输出
void print(LinkQueue* Q) {//前提为队不为空printf("(front) ");if (Q->front != Q->rear) {QNode* p = Q->front->next;while (p != NULL) {printf("%d ", p->data);p = p->next;}}printf("(rear)\n");
}
int main() {LinkQueue* Q = InitQueue();int i, n, e;scanf("%d", &n);for (i = 0; i < n; i++) {scanf("%d", &e);EnQueue(Q, e);}print(Q);DeQueue(Q, &e);printf("%d\n", e);print(Q);return 0;
}

总结

C语言 队列(循环队列和链队初始化进出队等基本操作)相关推荐

  1. C语言查看队头元素,C语言实现循环队列的初始化进队出队读取队头元素判空-1...

    目前,处在学习数据结构+ing,由于之前学过了队列,今天就把自己写过的代码做了一些完善分享给大家,希望能够帮助到有需要的朋友,有不足的地方欢迎大家交流    φ(゜▽゜*)♪ 队列是另一种限定性的线性 ...

  2. c语言while队列不为空,C语言实现循环队列的初始化进队出队读取队头元素判空-2...

    /*顺序表实现队列的一系列操作(设置flag标志不损失数组空间)*/ #include #include #define Queue_Size 50 //队列的最大长度 #define OK 1 #d ...

  3. 数据结构 队列(顺序队列 循环队列 链队列)

    目录 一.引入 二.队列的定义 三.队列的抽象数据类型 四.队列的存储方式 五.队列的顺序存储(不太常用 后面5.4会给出原因) 5.1顺序存储队列的基本知识点 5.2队列的顺序存储描述 5.3顺序存 ...

  4. 字符串队列c语言,C语言实现循环队列(队列可存储字符串)

    项目原因,需要写一个队列来存储串口实时输出的字符串.看了网上很多博文和一些数据结构的数据,给的例子都是实现对单个数字或者字符的队列操作,并没有实现在队列中存储字符串.这里分享一种可以实现的方法. 关于 ...

  5. Java实现队列(循环队列,链队列)

    循环队列: package SeqQueue;public class Queue {private int data[];private int queueSize;private int fron ...

  6. c语言变量循环队列的遍历操作,C语言实现循环队列

    对于循环队列有几个操作: 1.初始化 2.入队 3.出队 4.遍历队列 5.判队列空,判队列满 具体如何实现,我会在下面通过代码实现 在对循环队列操作之前,先要建立队列结构体元素, 1 typedef ...

  7. 数据结构c语言循环队列代码,数据结构C语言实现----循环队列

    代码如下: #include #include typedef char ElemType; #define MAXQUEUE 100 typedef struct { ElemType *base; ...

  8. 顺序循环队列类c#语言,C#--循环队列的顺序存储

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

  9. 队列----循环队列

    队列:只允许在一段进行插入,在另一端进行删除的线性表. 循环队列:具有队头指针和队尾指针,指示队列元素所在的位置,避免删除元素时移动大量元素. 循环队列特性: 只能队尾插入元素.在队头删除元素. 先进 ...

最新文章

  1. Spring Boot全面总结(超详细,建议收藏)
  2. iOS设计模式 - 生成器
  3. 图的实现(邻接链表C#)
  4. python web为什么不火-pythonweb为什么不火-问答-阿里云开发者社区-阿里云
  5. JDBC连接mysql--学习目录
  6. 收下这12篇最新论文,炼丹不愁没灵感 | 本周值得读
  7. C#文件和文件文件夹按时间、名称排序-顺序与倒序
  8. 如何在子网中访问上层网络的计算机文件夹
  9. 【Elasticsearch】es 别名可写 索引可写 傻傻分不清
  10. 微信开发 MySQL 存储 Emoji 表情
  11. 最短路径例题(Floyd、Dijkstra)
  12. 用友/U8+V16.0修改单据时,其他入库单其他出库单无保质期信息且置灰无法输入/修改
  13. 计算机视觉 相机成像原理,计算机视觉之相机成像原理与坐标系转换
  14. smbrun - smbd和外部程序间的接口程序。
  15. 机器学习 | 特征重要性判断
  16. 用python分析四大名著(一)
  17. 如何记账能简单高效,记账全攻略来了
  18. Hadoop的安装与配置(非常重要)
  19. 网络对抗 Exp9 Web安全基础 20154311 王卓然
  20. 使用IDL显示DICOM文件的信息

热门文章

  1. gateway的基本使用
  2. 深度学习(一):卷积运算
  3. mysql存储过程while循环语句
  4. 解决Tensorflow error(CUBLAS_STATUS_EXECUTION_FAILED)报错问题
  5. htb_Escape (mssql渗透,winrm)
  6. 【程序源代码】小程序商城系统(CoreShop)
  7. 在vscode中加参数调试-python
  8. form表单的onsubmit() return问题
  9. RTFM(Read The Fucking Manual)的意思(zt)
  10. 线程的状态 - Java