队列(Queue)是编程中最常用的数据结构之一。

  队列的特点是“先进先出”,就像食堂排队买饭一样,先来的人排在前面,后来的人排在后面;前面的人先买饭,买完饭后离开这个队列。这就是队列的原理,它可以进行入队列和出队列的操作,也就是说,队列限制用户只能在队列的前后两端进行操作,不能在中间进行操作。

  和线性表、栈相同,队列也有顺序的存储方式和链式的存储方式两种方式,分别称为顺序对和链队。与栈不同的是,队列可以在前后两个端点处进行增/删操作,因此,顺序队性能大大不如链队,链队是二者中比较常用的队列表示形式。

  下面的代码是使用 C语言 描述的链队的代码。

  队列的头文件Queue.h中的代码如下:

/**
* 队列(链式存储)
* 本程序中队列的存储方式:头节点->节点1->节点2->...->节点N,头结点中不存储数据
*/
#include <Constant.h> // 定义队列节点中数据的类型
typedef int ElemType; // 队列中节点的数据结构体
typedef struct QueueNode {
ElemType value;
struct QueueNode* nextNode;
} QueueNode; // 队列的结构体
typedef struct Queue {
QueueNode* data;
QueueNode* firstNode;
QueueNode* lastNode;
int length;
} Queue; // 初始化队列
Status initQueue(Queue* Q) {
Q->data = (QueueNode*)malloc(sizeof(QueueNode));
if(Q->data == NULL) {
printf("队列初始化失败!\n");
return FAILURE;
}
Q->data->nextNode = NULL;
Q->firstNode = NULL;
Q->lastNode = NULL;
Q->length = ;
return SUCCESS;
} // 销毁队列
Status destroyQueue(Queue* Q) {
QueueNode* node;
if(Q->data == NULL) {
printf("队列不存在,销毁失败!\n");
return FAILURE;
}
while(Q->data->nextNode != NULL) {
node = Q->data->nextNode;
Q->data->nextNode = node->nextNode;
free(node);
}
free(Q->data);
return SUCCESS;
} // 判断队列是否为空
Status isQueueEmpty(Queue* Q) {
if(Q->data == NULL) {
printf("队列不存在!\n");
exit();
}
if(Q->length == ) {
return TRUE;
}
return FALSE;
} // 清空队列
Status clearQueue(Queue* Q) {
QueueNode* node;
if(Q->data == NULL) {
printf("队列不存在,清空失败!\n");
return FAILURE;
}
while(Q->data->nextNode != NULL) {
node = Q->data->nextNode;
Q->data->nextNode = node->nextNode;
free(node);
}
return SUCCESS;
} // 获取队列中元素的个数
int getQueueSize(Queue* Q) {
if(Q->data == NULL) {
printf("队列不存在!\n");
exit();
}
return Q->length;
} // 查看队列中的第一个元素
QueueNode* getFirstElem(Queue* Q) {
if(Q->data == NULL) {
printf("队列不存在,获取第一个元素失败!\n");
return NULL;
}
if(Q->length == ) {
printf("队列是空队列,获取第一个元素失败!\n");
return NULL;
}
return Q->firstNode;
} // 查看队列中的最后一个元素
QueueNode* getLastElem(Queue* Q) {
if(Q->data == NULL) {
printf("队列不存在,获取最后一个元素失败!\n");
return NULL;
}
if(Q->length == ) {
printf("队列是空队列,获取最后一个元素失败!\n");
return NULL;
}
return Q->lastNode;
} // 元素入队列
Status appendElem(Queue* Q, ElemType e) {
QueueNode* newNode;
if(Q->data == NULL) {
printf("队列不存在,元素入队列失败!\n");
return FAILURE;
}
newNode = (QueueNode*)malloc(sizeof(QueueNode));
if(newNode == NULL) {
printf("元素入队列失败!\n");
return FAILURE;
}
newNode->value = e;
newNode->nextNode = NULL;
if(Q->data->nextNode == NULL) {
Q->data->nextNode = newNode;
Q->firstNode = newNode;
} else {
Q->lastNode->nextNode = newNode;
}
Q->lastNode = newNode;
Q->length++;
return SUCCESS;
} // 元素出队列
QueueNode* retrieveElem(Queue* Q) {
QueueNode* node;
if(Q->data == NULL) {
printf("队列不存在,元素出队列失败!\n");
return NULL;
}
if(Q->length == ) {
printf("队列是空队列,元素出队列失败!\n");
return NULL;
}
node = Q->data->nextNode;
Q->data->nextNode = node->nextNode;
Q->length--;
return node;
} // 遍历队列中的元素
void traverseQueue(Queue* Q) {
QueueNode* node;
if(Q->data == NULL) {
printf("队列不存在,遍历失败!\n");
exit();
}
if(Q->length == ) {
printf("队列是空队列,遍历失败!\n");
exit();
}
printf("遍历队列:");
node = Q->data;
while((node = node->nextNode) != NULL) {
printf("%-4d", node->value);
}
printf("\n");
} // 测试队列的方法
int testQueue() {
// 各种对象的声明
Queue queue;
QueueNode* node;
int i = ;
// 初始化队列
if(initQueue(&queue) == SUCCESS) {
printf("队列初始化成功!\n");
}
// 入队列
for(i = ; i <= ; i++) {
if(appendElem(&queue, i) == SUCCESS) {
printf("元素%d入队列成功!\n", i);
}
}
// 出队列
if((node = retrieveElem(&queue)) != NULL) {
printf("元素%d被移除队列\n", node->value);
}
// 查看队列中的第一个元素
if((node = getFirstElem(&queue)) != NULL) {
printf("队列中第一个元素的值是:%d\n", node->value);
}
// 查看队列中的最后一个元素
if((node = getLastElem(&queue)) != NULL) {
printf("队列中最后一个元素的值是:%d\n", node->value);
}
// 获取队列中元素的个数
printf("队列中元素的个数:%d\n", getQueueSize(&queue));
// 遍历队列中的元素
traverseQueue(&queue);
// 判断队列是否为空
printf("队列是否为空?%s\n", isQueueEmpty(&queue) == TRUE ? "是" : "否");
// 清空队列
if(clearQueue(&queue) == SUCCESS) {
printf("清空队列成功!\n");
}
// 销毁队列
if(destroyQueue(&queue) == SUCCESS) {
printf("队列销毁成功!\n");
}
}

  常量类 Constant.h 中定义了一些常量,其代码如下:

#include <stdio.h>
#include <stdlib.h> #define TRUE 1
#define FALSE 0 #define SUCCESS 1
#define FAILURE 0 typedef int Status;

  主函数所在的文件 main.c 中的代码如下:

#include <Queue.h>

int main() {
testQueue();
return ;
}

  运行结果如下:

队列初始化成功!
元素1入队列成功!
元素2入队列成功!
元素3入队列成功!
元素4入队列成功!
元素5入队列成功!
元素1被移除队列
队列中第一个元素的值是:1
队列中最后一个元素的值是:5
队列中元素的个数:4
遍历队列:2 3 4 5
队列是否为空?否
清空队列成功!
队列销毁成功! Process returned 0 (0x0) execution time : 1.743 s
Press any key to continue.

【数据结构】之队列(C语言描述)的更多相关文章

  1. C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载

    维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...

  2. 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)

    数据结构与抽象 Java语言描述 第4版 目录 前言引言组织数据序言设计类P.1封装P.2说明方法P.2.1注释P.2.2前置条件和后置条件P.2.3断言P.3Java接口P.3.1写一个接口P.3. ...

  3. 数据结构与算法分析——C语言描述 第三章的单链表

    数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...

  4. 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)

    #include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...

  5. 《数据结构与算法分析——C语言描述》ADT实现(NO.00) : 链表(Linked-List)

    开始学习数据结构,使用的教材是机械工业出版社的<数据结构与算法分析——C语言描述>,计划将书中的ADT用C语言实现一遍,记录于此.下面是第一个最简单的结构——链表. 链表(Linked-L ...

  6. 《数据结构与算法分析-Java语言描述》 分享下载

    书籍信息 书名:<数据结构与算法分析-Java语言描述> 原作名:Data Structures and Algorithm Analysis in Java 作者: 韦斯 (Mark A ...

  7. 《数据结构与算法分析:C语言描述_原书第二版》CH3表、栈和队列_reading notes

    表.栈和队列是最简单和最基本的三种数据结构.基本上,每一个有意义的程序都将明晰地至少使用一种这样的数据结构,比如栈在程序中总是要间接地用到,不管你在程序中是否做了声明. 本章学习重点: 理解抽象数据类 ...

  8. 《数据结构与算法分析——C语言描述》ADT实现(NO.02) : 队列(Queue)

    第三个结构——队列(Queue) 队列与上次的栈相反,是一种先进先出(FIFO)的线性表.写入时只暴露尾部,读取时只暴露头部. 本次只实现了数组形式的队列.原因是链表形式的队列极为简单,只需要实现简单 ...

  9. 使用链表实现队列------《数据结构与算法分析-C语言描述》

    经过ubuntu的gcc验证 一.头文件 que_link.h #ifndef _QUE_LINK_H_ #define _QUE_LINK_H_ struct que_record; typedef ...

  10. 使用数组实现队列----《数据结构与算法分析---C语言描述》

    一.h文件:my_que.h #ifndef _MY_QUE_H_ #define _MY_QUE_H_ struct QueRecord; typedef struct QueRecord* que ...

随机推荐

  1. ansible模块之yum、pip、service、corn、user、group

    ansible相关模块 yum rpm 和yum 的区别 rpm:全称redhat package manager (红帽包管理器) 不能解决包之间的依赖关系 yum:可以解决依赖关系 yum 源配置 ...

  2. Windows 10 + kali Linux 双系统安装教程(详细版)

    准备工具如下: kali Linux 镜像 准备一4G以上的U盘 制作U盘启动盘工具- Win32DiskImager 添加引导工具-EasyBCD 留出一个空的盘,哪个盘的空间比较大可以压缩出大概2 ...

  3. VSCode实现文献管理

    1 常用文献管理软件 常用的文献管理软件有mendely,zotero,endnote和Papers(需要付费),具体对比参考链接1.1.1.2 笔者只用过Mendely,当时综合考虑挑了Endnot ...

  4. 医生智能提醒小程序数据库设计心得——Legends Never Die

    数据库设计心得 根据我们小组数据库设计的整个流程,我们将整个数据库设计划分为两个具体的阶段,在每个阶段需要进行不同的准备,有不同的注意事项,接下来我们将结合在数据库设计过程中遇到的一些问题和困难,提出 ...

  5. SpringBoot之集成MyBatis

    引入工程依赖包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  6. [考试反思]1103csp-s模拟测试99: 美梦

    可能这次考得好的原因就是熬夜颓废到不算太晚?(啪) 但是是真心困. 考前跟akt说:我希望今天考一点那种不用动脑子,就是一直码的题. 然后开门T1一道线段树维护单调栈的板子我就...了 当时调了一上午 ...

  7. 原生JS实现call,apply,bind函数

    1. 前言 使用原生JS实现call和apply函数,充分了解其内部原理.call和apply都是为了解决改变this的指向.作用都相同,只是传参的方式不同.除了第一个参数外,call可以接受一个参数 ...

  8. 雷神领域(并查集真是个好东西)并查集+流氓dp

    考场上,整整看了半个小时以上的题目!!! 化简题意: 给定一个全0矩阵,一些坐标点(x,y)为1,当三个点可以构成一个直角三角形时(直角边长为整数)拓展为一个矩形,之后从(0,0)出发,求最多的占用行 ...

  9. Jenkins发送测试报告

    邮件全局配置 邮件插件:Email Extension Plugin 功能:发送邮件 邮件全局配置:jenkins--系统管理--系统配置:截图: 配置说明: 系统管理员邮件地址:必须配置,配置后邮件 ...

  10. Java实现不遍历数组求和

    package com.jts.t1; /** * 不遍历数组求和 * 方法省略异常检查 */ public class Demo1 { public static void main(String[ ...