队列(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. win10+MinGw+ffmpeg 编译

    一.安装MinGw+msys 下载 mingw-get-setup.exe 并安装,安装完成会弹出以下界面. 选中红色框几个选项,点击Installation->Apply Changes 进行 ...

  2. 用python实现对元素的长截图

    一.目标 浏览网页的时候,看见哪个元素,就能截取哪个元素当图片,不管那个元素有多长 二.所用工具和第三方库 python ,PIL,selenium pycharm 三.代码部分 长截图整体思路: 1 ...

  3. python多进程总结

    概述 由于python中全局解释器锁(GIL)的存在,所以python多线程并不能有效利用CPU多核的性能(相当于单核并发)实现多线程多核并行,所以在对CPU密集型的程序时处理效率较低,反而对IO密集 ...

  4. Java锁-Synchronized深层剖析

    Java锁-Synchronized深层剖析 前言 Java锁的问题,可以说是每个JavaCoder绕不开的一道坎.如果只是粗浅地了解Synchronized等锁的简单应用,那么就没什么谈的了,也不建 ...

  5. [LINQ2Dapper]最完整Dapper To Linq框架(六)---多表联合与匿名类型返回

    目录 [LINQ2Dapper]最完整Dapper To Linq框架(一)---基础查询 [LINQ2Dapper]最完整Dapper To Linq框架(二)---动态化查询 [LINQ2Dapp ...

  6. c#数据结构之Array、ArrayList、List、LinkedList对比分析

    一.前言: 在c#数据结构中,集合的应用非常广泛,无论是做BS架构还是CS架构开发,都离不开集合的使用,比如我们常见的集合包括:Array.ArrayList.List.LinkedList等.这一些 ...

  7. 关于设备与canvas画不出来的解决办法

    连续四天解决一个在三星手机上面画canvas的倒计时饼图不出来的问题,困惑了很久,用了很多办法,甚至重写了那个方法,还是没有解决,大神给的思路是给父级加 "overflow: visible ...

  8. getClass()和instanceof以及类的equals方法

    在比较两个类时,常见有两种做法,一种是x.getClass() == y; 一种是x instanceof y,下面我们来比较这两种做法的区别. getClass()返回一个对象所属的类 public ...

  9. CSS如何修改tr边框属性

    有很多时候,我们都要自定义为表格合并边框,这个只要 table{ border-collapse:collapse; } 就可以了 参数: separate 默认值.边框会被分开.不会忽略border ...

  10. Linux网络基本配置命令

    修改方法: 命令方式,大多是立即生效.临时有效: GUI图形方式, 修改配置文件,重启服务有效 1.修改主机名 hostname查看 hostname name临时修改 hostnamectl set ...