什么是队列?
队列(Queue)是一种基本的数据结构,它是一种先进先出(FIFO)的数据结构,它允许在一端插入元素,在另一端删除元素。队列的应用非常广泛,例如在操作系统中用于管理进程的调度,以及在网络中用于实现数据包的传输等。
队列的实现方式
队列可以使用数组或链表来实现。使用数组实现队列时,需要定义一个固定大小的数组,并使用两个指针来跟踪队列的头部和尾部。insert_queue 操作将元素添加到队列的尾部,而 delete_queue 操作则将队列的头部元素删除并返回。使用链表实现队列时,每个节点都包含一个数据元素和一个指向下一个节点的指针。insert_queue 操作将一个新节点添加到链表的尾部,而 delete_queue 操作则将头节点删除并返回其数据元素。
下面我们分别来看一下使用数组和链表实现队列的代码。
使用数组实现队列
以下是使用数组实现队列(循环队列)的示例代码:
#include <stdio.h>
#include <stdlib.h>
//构造循环队列
struct queue
{
int data[20];//定义一个大小为20的数组,用于储存数据
int size;//队列元素大小
int front;//队头指针
int rear;//队尾指针
};
//创建循环队列
struct queue *create()
{
//创建队列
struct queue *head = malloc(sizeof(struct queue));
//赋初值
head->size = 20;
head->front = 0;
//设置队头和队尾在同一个位置,作为初始条件
head->rear = head->front;
return head;
}
//插入——入队
void insert_queue(struct queue *head,int data)
{
//判断满(判断条件,差一个为满)
if((head->rear + 1) % head->size == head->front)
{
printf("队满\n");
return;
}
//插入
//在当前队尾位置插入
head->data[head->rear] = data;
//队尾指针向下移动一个位置
head->rear++;
}
//删除——出队
void delete_queue(struct queue *head)
{
//判断队列是否为空
if(head-front == head->rear)
{
printf("队空\n");
return;
}
//删除
//删除当前数据,没有直接删除空间,只能覆盖原数据内容
printf("出队元素:%d\n",head->data[head->front]);
//队头指针向后移动一个位置
head->front++;
}
//遍历
void show(struct queue *head)
{
//从队头 遍历到 队尾
for(int i = head->front;i != head->rear;)
{
printf("%d ",head->data[i]);
i = (i+1) % head->size;
}
printf("\n");
}
//获取队列元素个数
int count(struct queue *head)
{
return ((head->rear + head->size - head->frot) % head->size);
}
//主函数
int main()
{
//创建队列
struct queue * head = create();
//遍历队列
show(head);
delete_queue(head);
insert_queue(head,1);
delete_queue(head);
delete_queue(head);
insert_queue(head,1);
insert_queue(head,2);
insert_queue(head,3);
insert_queue(head,4);
insert_queue(head,5);
insert_queue(head,6);
insert_queue(head,7);
insert_queue(head,8);
show(head);
delete_queue(head);
delete_queue(head);
show(head);
return 0;
}
在这个示例代码中,我们使用一个数组 data来存储队列中的元素,使用变量 front
和 rear
来跟踪队列的头部和尾部。在 insert_queue 操作中,我们首先检查队列是否已满,如果已满则输出队满信息。如果队列未满,则将元素添加到队列的尾部,并将 rear 指针上移一位。在 delete_queue 操作中,我们首先检查队列是否为空,如果为空则输出为空信息。如果队列非空,则将队列的头部元素删除并返回。在 show 操作中,则遍历获取队列中所有元素。在 count 操作中,我们计算队列中元素的数量,并返回。最后调用了主函数来进行了简单的测试顺序栈的插入、删除、遍历功能。
使用链表实现队列
以下是使用链表实现队列的示例代码:
#include <stdio.h>
#include <stdlib.h>
//构造结点
struct Node {
int data;
struct Node* next;
};
//构造队头、队尾指针
struct pque
{
struct Node* front;
struct Node* rear;
};
//创建链式队列,返回值为 队头队尾指针结构体
struct pque * create()
{
//创建头结点,作为空队列开始
struct Node *head = malloc(sizeof(struct Node));
head->next = NULL;
//创建队头和队尾指针
struct pque *p = malloc(sizeof(struct pque));
//设置队头队尾的初始值
p->front = head;
p->rear = p->front;
return p;
}
//入队
void insert_que(struct pque *que,int data)
{
//1、创建新结点
struct Node *new = malloc(sizeof(struct Node));
new->data = data;
//2、修改队尾结点,插入下一个
//通过队尾指针来找到最后结点
new->next = que->rear->next;
que->rear->next = new;
//3、修改队尾指针,存储新结点地址
que->rear = new;
}
//出队
void delete_que(struct pque *que)
{
//为空
if(que->front->next == NULL)
{
printf("队空\n");
return;
}
//删除
//1、存储要删除的结点
struct Node *p = que->front->next;
printf("出队元素:%d\n",p->data);
//2、移动队头指针
que->front->next = p->next;
//如果队尾就是第一个,删除的是队尾,这时需要改变队尾指针
if(p->next == que->rear)
{
que->rear = que->front;
}
//3、删除结点
free(p);
}
//遍历
void show(struct pque *que)
{
//p存储头结点地址
struct Node * p = que->front;
while( p->next != NULL )
{
p = p->next;
printf("%d ",p->data);
}
printf("\n");
}
//主函数
int main()
{
struct pque * que = create();
show(que);
delete_queue(que);
insert_queue(que,1);
insert_queue(que,2);
insert_queue(que,3);
insert_queue(que,4);
insert_queue(que,5);
insert_queue(que,6);
insert_queue(que,7);
show(que);
delete_queue(que);
delete_queue(que);
show(que);
insert_queue(que,20);
show(que);
return 0;
}
在这个示例代码中,我们使用一个链表来实现队列。每个结点包含一个数据元素和一个指向下一个节点的指针。构造了队头、队尾结构体用于指向结点。在 insert_queue 操作中,我们创建一个新节点,并将其指针指向当前的 rear 结点。然后将 rear 指针移动到新节点。在 delete_queue 操作中,我们首先检查队列是否为空,如果为空则输出为空信息。如果队列非空,则将 front 指针移动到下一个结点,则将队列的头部元素删除并输出。在 show 操作中,则遍历获取队列中所有元素。最后调用了主函数来进行了简单的测试顺序栈的插入、删除、遍历功能。
队列的应用场景
队列是一种非常有用的数据结构,它可以用于许多不同的应用程序。以下是一些常见的应用场景:
- 进程调度:在操作系统中,队列用于管理进程的调度。每当一个进程被创建时,它被添加到就绪队列中,等待 CPU 时间片的分配。当一个进程完成时,它被添加到完成队列中。
- 数据包传输:在网络中,队列用于实现数据包的传输。每当一个数据包到达时,它被添加到发送队列中,等待发送。当一个数据包被成功发送时,它被添加到接收队列中,等待接收方的处理。
- 银行排队:在银行等服务场所中,队列用于管理客户的排队。每当一个客户到达时,他被添加到队列中,等待服务员的处理。当一个客户完成时,他被从队列中删除。
总结
队列是一种非常有用的数据结构,它可以用于许多不同的应用程序。队列可以使用数组或链表来实现,每种实现方式都有其优点和缺点。在实现队列的过程中,需要注意队列是否为空或已满,以及内存分配和释放等问题。