本篇博客带来栈的好兄弟——队列。

目录

一、 队列的概念与结构

二、 队列的框架定义

三、 队列的功能实现

3.1 队列的初始化

3.2 队列的销毁

3.3 队列插入数据

3.4 队列删除数据

3.5 队列的判空

3.6 取头部数据

3.7 取尾部数据

3.8 队列的大小

四、功能测试

五、总结


一、 队列的概念与结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出(First In First Out)的特性。入队列:进行插入操作的一端称之为队尾;出队列:进行删除操作的一段称之为队头。

二、 队列的框架定义

队列也可以使用数组或链表实现,使用链表的结构实现更有一些,因为如果使用数组的结构,出队列在数组0下标处上出数据,效率会比较低。

接下来我们来看看此次要实现的队列基本操作。

#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <assert.h>typedef int QDataType;
typedef struct QueueNode
{struct QueueNode* next;QDataType data;
}QNode;typedef struct Queue
{QNode* head;QNode* tail;
}Queue;void QueueInit(Queue* pq);                //队列的初始化
void QueueDestroy(Queue* pq);             //队列的销毁
void QueuePush(Queue* pq, QDataType x);   //插入数据
void QueuePop(Queue* pq);                 //删除数据
bool QueueEmpty(Queue* pq);               //队列的判空
QDataType QueueFront(Queue* pq);          //队列头部数据
QDataType QueueBck(Queue* pq);            //队列尾部数据
int QueueSize(Queue* pq);                 //队列的大小

注意:

栈使用的是数组,数组是可以直接访问的。而如果我们使用链表实现队列,则要设置一个head和tail指针表示队头和对尾,其中head和tail都为普通的单链表节点结构,所以它们要设置next指针域和data数据域,这样才能实现队列的特性。

三、 队列的功能实现

3.1 队列的初始化

和之前实现的单链表初始化差不多,这里就不过多讲解了。

void QueueInit(Queue* pq)
{assert(pq);pq->head = pq->tail = NULL;
}

3.2 队列的销毁

因为是链表的形式,所以我们释放空间不能像数组一样直接整段释放,要使用while将每个节点释放掉。

void QueueDestroy(Queue* pq)
{assert(pq);QNode* Dest = pq->head;while (Dest){QNode* temp = Dest->next;free(Dest);Dest = temp;}pq->head = pq->tail = NULL;
}

3.3 队列插入数据

队列插入数据的步骤:

将newnode链接到head节点的next;将newnode设置为新的tail节点。

这里我们注意,在我们初始化的时候,我们将head和tail节点都置为了NULL,所以在我们第一次插入数据的时候要做一次判断,如果(head==NULL),则要将tail和head都设置为newnode节点,这样才能保证链表正常链接起来。

注释写的很详细,大家可以看看。

void QueuePush(Queue* pq, QDataType x)
{assert(pq);//创建一个节点QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){printf("malloc fail\n");exit(-1);}newnode->data = x;newnode->next = NULL;//判断pq是不是一个空结点//如果是 则将newnode置为当前队列的第一个结点//如果不是  则将newnode链接到pq的下一个位置if (pq->tail == NULL){   //两个节点都指向newnode 表示此时队列中就一个元素pq->head = pq->tail = newnode;}else {//1.将newnode链接到tail的后面pq->tail->next = newnode;//2.将newnode置换为新的tailpq->tail = newnode;}
}

3.4 队列删除数据

上文就提到过,队列是先进先出,所以我们删除数据要从队头删除

队列删除数据的步骤:

保存head下一个节点的位置

释放head节点

将保存的节点设置为新的head。

注意:

        ①要先判断队列不能为空

        ②如果队列中仅剩一个节点的时候,我们按以上的步骤释放了head节点并将其置为了NULL,但是我们没有处理tail节点,此时tail节点就成了经典的野指针。所以我们要额外判断当节点仅剩一个的时候,即(pq->head->next==NULL),我们要释放head结点,并将其head和tail都置为NULL。

代码如下:

void QueuePop(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));//额外判断一下,解决如果仅剩一个结点了,pop的话导致tail为野指针if (pq->head->next == NULL){free(pq->head);pq->head = pq->tail = NULL;}else{QNode* next = pq->head->next;free(pq->head);pq->head = next;}
}

3.5 队列的判空

队列如何判空呢?

此时我们只用判断head是否为NULL即可,即(head->next==NULL);

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->head == NULL;
}

3.6 取头部数据

注意: 这些取数据和删除数据的操作都要先判断队列是否为空。

QDataType QueueFront(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->head->data;
}

3.7 取尾部数据

QDataType QueueBck(Queue* pq)
{assert(pq);assert(!QueueEmpty(pq));return pq->tail ->data;
}

3.8 队列的大小

链表不数组可以通过计算下标来算长度,所以这里我们只能使用循环计算直到cur==NULL;

int QueueSize(Queue *pq)
{assert(pq);int count = 0;QNode* cur = pq->head;while (cur){cur = cur->next;count++;}return count;
}

四、功能测试

还是和栈一样的测试方式来检查我们队列实现是否成功。

同样,队列是不能遍历的,所以我们也要采用取出一个队列头部数据,然后将头部数据弹出,直到队列为空。

五、总结

相比于栈,队列的性质与栈的截然不同,同样我们这里使用的链式结构与数组的形式也不同。

我感觉实现队列唯一的难点可能就是其中两层结构体的灵活使用吧,其他的与栈的实现很类似,大家可以把队列的框架定义看看,然后自己实现一下,这对于掌握结构体很有帮助,对队列的认识也会加深。

好了,本篇博客到此就结束了,接下来做几道题目之后就会开始树的学习,一段全新的征程,大家一起学习数据结构,一起加油。

队列的基本操作(C语言实现)相关推荐

  1. 队列的基本操作c语言代码大全,数据结构――队列(循环队列)的基本操作(实现链队列逐一取出c语言代码)...

    队列 队列是一种重要的线性结构,与栈相同也需要顺序表或者链表作为基础.队列是先进先出(first in first out)FIFO的线性表. 所有数据从队列的一端进入,从另一端离开. 队列中允许插入 ...

  2. 数据结构之【队列】的基本操作C语言实现

    直接上图: 循环队列的声明: 0.循环队列的声明 循环队列的基本操作: 1.InitQueue(&Q)(构造一个空队列) 2.DestroyQueue(&Q)(销毁队列Q) 3.Cle ...

  3. C语言循环队列的基本操作(init,enquene,dequene)与杨辉三角(C和C++<queue>)

    C语言循环队列的基本操作与杨辉三角(C和C++的表示方法) C语言的表示方法 #include <stdio.h> #include <malloc.h> #define ma ...

  4. 魔王语言C语言 使用头文件封装 链表链栈顺序队列的基本操作

    1.抽象数据类型的定义和说明: a) 链栈类型 由于沿用了链表,因此此处列出修改后的链表抽象数据类型 SElemType:数据结点,内含一个char型的数据zi; SqStack:栈,包含存储空间基址 ...

  5. (C语言版)栈和队列(一)——实现链式栈和链式队列的基本操作以及遇到的问题

    http://blog.csdn.net/fisherwan/article/details/20055179 首先要感谢这位大牛的一篇博客,地址如下:http://blog.csdn.net/hgu ...

  6. 利用队列的基本操作,完成舞伴问题

    题目 利用队列的基本操作,完成舞伴问题 舞伴问题的描述:假设在周末舞会上,男士们和女士们进入舞厅时各自排成一队,跳舞开始时,依次从男队和女队的队头上各出一人配成舞伴,若两队初始人数不相同,则较长的那一 ...

  7. java栈和队列验证回文串_栈和队列的基本操作及其应用(回文判断)

    实验二栈和队列的基本操作及其应用 一.实验目的 1.掌握栈和队列的顺序存储结构和链式存储结构,以便在实际中灵活应用. 2.掌握栈和队列的特点,即后进先出和先进先出的原则. 3.掌握栈和队列的基本运算, ...

  8. 数据结构——链式队列解析(C语言版)

    摘自:数据结构学习--链式队列解析(C语言版) 作者:正弦定理 发布时间:2020-11-26 21:07:08 网址:https://blog.csdn.net/chinesekobe/articl ...

  9. 顺序循环队列的基本操作

    [问题描述] 实现循环队列的基本操作.(循环队列最大长度不超过20) [输入形式] 输入若干个整数(以空格分隔,非整数结束输入),其中0表示做出队操作,不为0的整数为入队元素. [输出形式] 若出队错 ...

最新文章

  1. EEGLAB处理脑电视频教程 part1-3
  2. AJAX开发简略 (转)
  3. 何谓 SQL 注入,这个漫画告诉你!
  4. eval 函数 代替函数_eval()函数以及JavaScript中的示例
  5. [转载] --- Fastjson1.2.68版及以下全版本远程代码执行漏洞通告
  6. Dijkstra Algorithm (迪杰斯特拉算法)
  7. python画折线图虚线_python绘制简单折线图代码示例
  8. knight tour java,Knight Tour Problem
  9. Jzoj5421 嘟嘟噜
  10. cefsharp作为采集工具(学习笔记)
  11. 企业实战——Ansible自动化运维基础知识
  12. ArcGis如何创建/连接企业级地理数据库
  13. appium ios 下拉刷新输入框输入后收起键盘
  14. JMockit @mocked 注释标签
  15. log4j2 日期换天后,今天的日志打印到了昨天的日志文件里面,rollover混乱
  16. linux上卸载php,linux怎么卸载软件?
  17. 如何解决WIN10处于通知模式的问题?
  18. 做好OKR目标管理,迈出高效协作的第一步
  19. ppt打印铺满纸张时的设置方法
  20. GBK编码具体解析(附GBK码位分布图)

热门文章

  1. 大地测量学—投影变形(高程归化改正+高斯投影改正)
  2. ps与pstree小结
  3. ssm+jsp计算机毕业设计自动阅卷系统5d7xo(程序+lw+源码+远程部署)
  4. .NET 6 实现敏感词过滤
  5. python爬虫基本框架代码(入门)
  6. 计算机中考在线评分模拟卡,TOP30广西南宁市2016届中考权威预测模拟数学试卷一解析版.doc文档免费在线阅读(模版2)...
  7. Mac 10.13安装openVPN
  8. 自学Java半年,能找到工作嘛?
  9. python成语填空_python一步一步解析成语
  10. 7月29日所学Python基础