在我们的日常生活中,队列是一个非常常见的现象。无论是在商店结账,还是在公交站等车,我们都在使用队列。在计算机科学中,队列也是一个重要的数据结构,用于处理和组织数据。在这篇文章中,我们将详细探讨队列的定义、操作、以及如何用C语言实现队列。
队列(Queue)是一种特殊类型的线性数据结构,它遵循特定的操作规则,即遵循“先进先出”(FIFO,First-In-First-Out)原则。这意味着在队列中,首先加入的元素将会首先被移除,最后加入的元素将会最后被移除。
当我们想存入1时,先移动front(队头)然后再写入数据1,拿数据也是一样,但务必保证先移动rear(队尾),再拿出数据,否则将会错位导致出错。
首先需要定义一个顺序队列,我们可以使用结构体来定义一个队列,它包含一个数组(用于存储队列的数据)和三个整数(用于表示队列长度、队首和队尾的位置)。
typedef int Datatype;
//队列的结构体定义
typedef struct Quene
{
Datatype *q; //用来存放队列的数据
int size; //队列的长度
int front; //队头
int rear; //队尾
}queue;
接下来,我们需要初始化队列。在初始化时,我们将队首和队尾都设置为0,表示队列为空。
//初始化一个队列
queue *init_queue(int size)
{
queue *que = malloc(sizeof(queue));
if (que!=NULL)
{
que->q = calloc(size, sizeof(Datatype));
que->size = size;
que->front = 0;
que->rear = 0;
}
return que;
}
如果我们想要实现入队和出队操作,我们需要先考虑队列可能会溢出或下溢的情况,因此我们需要判断是否队空或队满。
//队空判断
bool isempty_queue(queue *q)
{
return (q->rear == q->front);
}
//队满判断
bool isfull_queue(queue *q)
{
return ((q->rear+1)%q->size == q->front);
}
//入队
bool en_queue(queue *que, Datatype data)
{
if (isfull_queue(que))
{
return false;
}
//先挪rear
que->rear = (que->rear+1)%(que->size);
//再入数据
que->q[que->rear] = data;
return true;
}
//出队
bool de_queue(queue *que, Datatype *data)
{
if (isempty_queue(que))
{
return false;
}
//先挪front
que->front = (que->front+1)%(que->size);
//再取数据
*data = que->q[que->front];
return true;
}
队列是计算机科学中的一个基础概念,它在许多场景中都有应用,如操作系统的任务调度,网络的数据包处理等。理解队列的工作原理并能够实现队列,对于学习和理解计算机科学的其他概念是非常有帮助的。希望这篇文章能帮助你理解和实现队列。
下面是一个简单的顺序队列举例,实现:输入正整数,添加员工信息,入队,用这个正整数表示员工号;输入负整数,出队(队首),显示该员工的所有信息;否则就退出。
员工信息:工号、姓名、工资
完整源码:
#include
#include
#include
#define SIZE 1024
typedef struct people
{
int number; //工号
char name[20]; //姓名
int money; //工资
}Datatype;
//队列的结构体定义
typedef struct Quene
{
Datatype *q; //用来存放队列的数据
int size; //队列的长度
int front; //队头
int rear; //队尾
}queue;
//初始化一个队列
queue *init_queue(int size)
{
queue *que = malloc(sizeof(queue));
if (que!=NULL)
{
que->q = calloc(size, sizeof(Datatype));
que->size = size;
que->front = 0;
que->rear = 0;
}
return que;
}
//队空判断
bool isempty_queue(queue *q)
{
return (q->rear == q->front);
}
//队满判断
bool isfull_queue(queue *q)
{
return ((q->rear+1)%q->size == q->front);
}
//入队
bool en_queue(queue *que, Datatype data)
{
if (isfull_queue(que))
{
return false;
}
//先挪rear
que->rear = (que->rear+1)%(que->size);
//再入数据
que->q[que->rear] = data;
return true;
}
//出队
bool de_queue(queue *que, Datatype *data)
{
if (isempty_queue(que))
{
return false;
}
//先挪front
que->front = (que->front+1)%(que->size);
//再取数据
*data = que->q[que->front];
return true;
}
// 添加信息
void init_info(Datatype *data,int n)
{
data->number = n;
printf("请输入工人信息\n");
while(getchar() != '\n');
printf("姓名:");
scanf("%s", data->name);
printf("工资:");
scanf("%d", &data->money);
}
int main(int argc, char const *argv[]) {
queue *q = init_queue(SIZE);
int n;
Datatype data;
while (1)
{
printf("请输入一个正整数或负数\n");
scanf("%d", &n);
if (n > 0){
init_info(&data, n);
en_queue(q, data);
continue;
}
else if(n < 0){
Datatype d;
if (de_queue(q, &d)) {
printf("工号:%d,姓名:%s,工资:%d\n", d.number, d.name, d.money);
} else {
printf("队列已空,无法出队。\n");
}
}
else{
return -1;
}
}
free(q->q);
free(q);
return 0;
}
链式队列(Linked Queue)是一种使用链表来实现的队列数据结构。与顺序队列不同,链式队列的元素并不直接存储在数组中,而是通过链表节点来连接。
并且 由于使用链表实现,链式队列的大小可以根据需要动态分配和释放内存,避免了固定数组大小可能带来的限制。因此就没有是否队满问题。
typedef int Datatype;
typedef struct Node
{
Datatype data;
struct Node *next;
}node;
typedef struct List_queue
{
node *rear; //队尾指针
node *front; //队头指针
int size; //链式队列的长度(实际的元素的个数)
}L_q;
//创建新节点
node *create_node(Datatype data)
{
node *new = malloc(sizeof(node));
if (new != NULL)
{
new->data = data;
new->next = NULL;
}
return new;
}
//链式队列是否为空
bool isempty_list_queue(L_q *q)
{
return (q->size == 0);
}
//初始化链式队列
L_q *init_list_queue()
{
L_q *q = malloc(sizeof(L_q));
if (q!=NULL)
{
q->rear = NULL;
q->front = NULL;
q->size = 0;
}
return q;
}
入队操作在链表的末尾添加一个新节点,同时更新队尾指针。
//入队
bool en_list_queue(L_q *q, Datatype data)
{
//先要将数据创建新节点
node *new = create_node(data);
if (new==NULL)
{
return false;
}
//如果是第一次入队,new节点既是队尾,也是队头
if (isempty_list_queue(q))
{
q->rear = new;
q->front = new;
}
else //不是第一次入队
{
//先将尾部节点的next指向new节点
q->rear->next = new;
//尾部节点要变成新节点new
q->rear = new;
}
//队的元素个数要+1
q->size++;
return true;
}
出队操作移除链表的第一个节点,同时更新队头指针。
//出队
bool de_list_queue(L_q *q, Datatype *data)
{
if (isempty_list_queue(q))
{
return false;
}
else if(q->size == 1)//只有一个数据的时候
{
q->rear = NULL;
}
//在链表不为空的情况下,先拿队头的数据
*data = q->front->data;
//将队头指向下一个节点
q->front = q->front->next;
//链式队列的元素个数-1
q->size--;
return true;
}
//遍历
void display(L_q *q)
{
if (q->front == NULL)
{
return ;
}
node *p = q->front;
while(p->next != NULL)
{
printf("%d ", p->data);
p = p->next;
}
printf("%d\n", p->data);
}
简单示例:当我们输入正数时,入队并遍历整个队列;当我们输入负数时,出队一个元素,并再次遍历队列;输入0时退出。
int main(int argc, char const *argv[])
{
L_q *q = init_list_queue();
int num;
Datatype data;
while(1)
{
scanf("%d", &num);
if(num > 0)
{
en_list_queue(q, num);
display(q);
}
else if(num < 0)
{
de_list_queue(q, &data);
display(q);
}
else
{
break;
}
}
return 0;
}
队列作为一种基本的数据结构,在我们的编程生涯中扮演着重要的角色。希望这篇文章提供了一个清晰、详细的队列概述,帮助你理解队列的基本概念和操作,以及如何用C语言实现队列。
选择顺序队列还是链式队列取决于实际应用的需求。如果你需要一个固定大小的队列,可以考虑使用顺序队列。如果你希望队列大小能够根据需要进行动态调整,那么链式队列更适合。在大多数情况下,链式队列具有更好的扩展性和灵活性。
更多C语言、Linux系统、ARM板实战和数据结构相关文章,关注专栏:
手撕C语言
玩转linux
脚踢数据结构
6818(ARM)开发板实战
一键三连喔
~