队列(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. SpringBoot + Redis 执行lua脚本

    1.背景 有时候,我们需要一次性操作多个 Redis 命令,但是 这样的多个操作不具备原子性,而且 Redis 的事务也不够强大,不支持事务的回滚,还无法实现命令之间的逻辑关系计算.所以,一般在开发中 ...

  2. Linux基本指令与作用

    在Linux操作系统中,有不同于windows的操作,可以用指令来进行操作. 指令 ls:查看文件 ls -a:查看隐藏文件 cd:移动到某个路径之中 clear:清屏rm:删除touch:创建mv: ...

  3. js实现的几种继承方式

    他山之石,可以攻玉,本人一直以谦虚的态度学他人之所长,补自己之所短,望各位老师指正! 拜谢 js几种继承方式,学习中的总结: 所谓的继承是为了继承共有的属性,减少不必要代码的书写 第一种:借用构造函数 ...

  4. RabbitMQ-交换机模式

    在说正题之前先解释一下交换机模式是个笼统的称呼,它不是一个单独的模式(包括了订阅模式,路由模式和主题模式),交换机模式是一个比较常用的模式,主要是为了实现数据的同步. 首先,说一下订阅模式,就和字面上 ...

  5. 关于数论分块里r=sum/(sum/l)的证明!

    今天的模拟赛里T2要使用到数论分块,里面有一个重要的坎就是关于r=sum/(sum/l)的证明,网上关于这道题的题解里都没有关于这个的证明,那么我就来填补一下: 在以下的文章里,我都会使用lo(x)表 ...

  6. 如何处理消息队列消费过程中的重复消息&如何实现幂等性

    什么是幂等 幂等本来是数学上的概念,它的定义是这样的: 如果一个函数 f(x) 满足:f(f(x)) = f(x),则函数 f(x) 满足幂等性. 在计算机领域用来描述一个操作.方法或者服务.一个幂等 ...

  7. docker简介及安装

    Docker : 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...

  8. GitHub和Git

    GitHub托管项目代码 首先一些基本概念: repository(仓库) 用来存放项目代码,每个项目代表一个仓库,开一个项目就意味着你有一个仓库. star(收藏) 收藏方便下次查找. fork(复 ...

  9. PHP实现微信企业付款到个人零钱步骤

    微信支付企业付款到零钱功能应用广泛,比如微信红包奖励,业务结算等.通过企业向个人付款,付款资金将直接进入用户微信零钱. 一 开通条件 ​ 付款资金 企业付款到零钱资金使用商户号余额资金. 根据商户号的 ...

  10. Thrift总结(四)Thrift实现双向通信

    前面介绍过 Thrift 安装和使用,介绍了Thrift服务的发布和客户端调用,可以查看我之前的文章:https://www.cnblogs.com/zhangweizhong/category/10 ...