1.队列的概念

在开始前,请牢记这句话:队列是一个先进先出的数据结构。

队列(queue)是限定在表的一端进行插入,表的另一端进行删除的数据结构,如同栈的学习,请联系前文所学链表,试想一个单链表,我们只能对他的链表表尾进行插入,而只能对链表的表头进行结点的删除,其余一切的操作均不允许,这样强限制性的“链表“,就是我们所说的队列。

让我们重新理顺一下定义:队列是一个线性的数据结构,规定这个数据结构只允许在一端进行插入,另一端进行删除,禁止直接访问除这两端以外的一切数据。

队列

如图:队列就像一个两端相通的水管,只允许一端插入,另一端取出,先放入管中的球先从管中拿出。


2. 队列的结点设计与初始化

队列不如栈那般方便进行模拟,因此队列只有链式的设计方法,但是不同的是,队列本身分为多种队列,如顺序队列(就是此文所讲队列)和循环队列(下一篇文章所讲),以及后文在C++STL章中会提到的优先队列等等,均来自于队列的衍生。

我们以顺序队列的设计为例。

首先是队列的结点设计,我们可以设计出两个结构体,一个结构体Node表示结点,其中包含有一个data域和next指针(可以发现,这样的结点设计我们已经重复出现了很多次了,正是因为这样的结构设计方便理解)。


队列的结点(图表示结点)


其中data表示数据,其可以是简单的类型(如int,double等等),也可以是复杂的结构体(struct类型)。

next指针表示,下一个的指针,其指向下一个结点,通过next指针将各个结点链接。

如同栈再次设计一个结构体进行限制性设计,接着,我们也额外添加一个结构体,其包括了两个分别永远指向队列的队尾和队头的指针,我们主要的操作只对这两个指针进行操作。

队列设计(图表示队列设计)


其结构体设计的代码可以表示为:

//结点定义
typedef struct node{
    int data;
    struct node *next;
}node;
//队列定义,队首指针和队尾指针
typedef struct queue{
    node *front;    //头指针
    node *rear;     //尾指针
}queue;

有关初始化,稍微复杂一点的是,我们对于初始化需要初始化两个类型,一个是初始化结点,一个是初始化队列,初始化队列稍微有些不同,那就是当初始化队列的时候,需要将头尾两个结点指向的内容统统制空,表示是一个空队列,两个创建的函数代码可以表示为:

//初始化结点
node *init_node(){
    node *n=(node*)malloc(sizeof(node));
    if(n==NULL){    //建立失败,退出
        exit(0);
    }
    return n;
}
 
//初始化队列
queue *init_queue(){
    queue *q=(queue*)malloc(sizeof(queue));
    if(q==NULL){    //建立失败,退出
        exit(0);
    }
    //头尾结点均赋值NULL
    q->front=NULL;  
    q->rear=NULL;
    return q;
}

3. 判断队列是否为空

判断队列是否为空比较简单,直接就是判断队列头指针是否是空值即可(关联如何创建队列可更好理解),判断队列是否为空是比较常用的操作。

其代码可以表示为:

//队列判空
int empty(queue *q){
    if(q->front==NULL){
        return 1;   //1--表示真,说明队列非空
    }else{
        return 0;   //0--表示假,说明队列为空
    }
}

或者直接利用返回值进行更简单的判断(两者效果完全一样)

int empty(queue *q){
    return q->front==NULL;
}


点赞(0)

C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:

一点编程也不会写的:零基础C语言学练课程

解决困扰你多年的C语言疑难杂症特性的C语言进阶课程

从零到写出一个爬虫的Python编程课程

只会语法写不出代码?手把手带你写100个编程真题的编程百练课程

信息学奥赛或C++选手的 必学C++课程

蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程

手把手讲解近五年真题的蓝桥杯辅导课程

Dotcpp在线编译      (登录可减少运行等待时间)