C语言 队列 的基本功能和详细代码(含详细注释)

本文深入探讨了队列这一特殊线性表的概念及其结构,详细介绍了队列的先进先出(FIFO)特性,并通过链表实现队列,包括初始化、入队、出队等核心操作。同时,提供了队列实现的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的规则FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
其实队列换一种说法就是我们文明生活中的 排队问题,不管干什么一般总是遵守先来后到的,
就是先来的(对头)先获取到资源,后来的不准插队,只能在最后面(队尾)排队等待。

如图所示:
队列概念图

队列的实现:

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,会一一移动后面的数据,效率会比较低。
下面用链表结构实现队列
推荐使用多文件的写程序方式,不仅利于阅读和查看,而且对以后进入公司也有帮助
头文件:
1.链式队列的结构和表示
2.基本功能的声明

#pragma once

#include <stdio.h>
#include <malloc.h>

typedef int QuDataType;
// 链式结构:表示队列
typedef struct QListNode
{
	struct QListNode* _next;
	QuDataType _data;
}QueueNode;

// 队列的结构
typedef struct Queue
{
	QueueNode* _front;
	QueueNode* _rear;
}Queue;

// 初始化队列
void QueueInit(Queue* q);

// 队尾入队列
void QueuePush(Queue* q, QuDataType data);

// 队头出队列
void QueuePop(Queue* q);

// 获取队列头部元素
QuDataType QueueFront(Queue* q);

// 获取队列队尾元素
QuDataType QueueBack(Queue* q);

// 获取队列中有效元素个数
int QueueSize(Queue* q);

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q);

// 销毁队列
void QueueDestroy(Queue* q);

函数定义文件
各个基本功能的定义实现
具体需要注意的都在里面的注释里

#include "Queue.h"
//一个数据入队列必须要先创建节点
QueueNode * BuyQueueNode(QuDataType x)    //创建节点并初始化此节点
{
	QueueNode * cur = (QueueNode *)malloc(sizeof(QueueNode));
	cur->_data = x;
	cur->_next = NULL;
	return cur;
}
void QueueInit(Queue* q) //初始化队列结构
{
	q->_front = NULL;
	q->_rear = NULL;
}
void QueuePush(Queue* q, QuDataType x)  //队列尾部入数据
{
	QueueNode * cur = BuyQueueNode(x);  //先把创建好的节点传过来
	if (q->_front == NULL)             //若是队列本身为空,队列里就只有这一个节点,又为队列头又为队列尾
	{
		q->_front = q->_rear = cur; 
	}
	else
	{
		q->_rear->_next = cur; //否则,链表尾插操作
		q->_rear = cur;
	}
}
void QueuePop(Queue* q)     //队列头部出数据
{
	if (q->_front == NULL)    //本身队列为空,不做操作
	{
		return;
    }
	QueueNode* tmp = q->_front->_next;   //先保留下一个节点,防止断链
	free(q->_front);
	q->_front = tmp;   //更新对列头部
}
QuDataType QueueFront(Queue* q)   //获取队列首部元素
{
	return q->_front->_data;
}
QuDataType QueueBack(Queue* q)//获取队列尾部元素
{
	return q->_rear->_data;
}
int QueueEmpty(Queue* q)   //判断队列是否为空
{
	return q->_front == NULL;   //为空,返回1
}
int QueueSize(Queue* q)  //获取队列中的元素个数
{
	QueueNode * cur;
	int count = 0;
	for (cur = q->_front; cur; cur = cur->_next)//循环遍历,计数即可
	{
		count++;
	}
	return count;
}
void QueueDestory(Queue* q)  //销毁队列
{
	if (q->_front == NULL)
	{
		return;
	}
	while (q->_front)
	{
		QueuePop(q);//对每一个元素迭代出队即可
	}
}

对实现的功能的简单测试

#include "Queue.h"

int main()
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);

	printf("%d\n", QueueFront(&q)); //1
	QueuePop(&q);//出队列
	printf("%d\n", QueueFront(&q));//2   此时队首为2

	printf("%d\n", QueueBack(&q));//4  队尾为4

	return 0;
}
#include #include #include //队列最大长度 #define MAX_QUEUE 1024 //偷懒,就用静态队列了 static int mQueue[MAX_QUEUE]; //队列插入 void InsertData(int **Front, int **Rear) { if (*Rear + 1 == *Front && (*Rear + 1 - MAX_QUEUE != *Front)) { //当队列数据已满,返回 puts("Queue Size Overflow!\n"); return; } else if (*Rear - mQueue > MAX_QUEUE) { //实现的是类似循环队列,但由于是静态线性队列(数组) //而不是用链表来实现的,所以到静态队列(数组)尾部,尾指针自动指向(数组)头部 *Rear = mQueue; } puts("Input Data:"); scanf("%d", *Rear); //输入数据后,尾指针后移 *Rear += 1; } //从头指针删除一个队列中的数据 void DeleteData(int **Front, int **Rear) { if (*Front == *Rear) { //头指针尾指针重合,队列空,不能删除,返回 puts("Queue Empty!\n"); return; } else if (*Front - mQueue > MAX_QUEUE) { //参考 Rear *Front = mQueue; } //从头指针删除一个数据 *Front += 1; } //显示队列数据 void ShowData(int **Front, int **Rear) { int *temp; for (temp=*Front; temp!=*Rear; temp++) { printf("%d --> ", *temp); } puts("\n"); } void usage(void) { puts("1. Insert Data"); puts("2. Delete Data"); puts("3. Show Data"); } int main(int argc, char **argv) { //头指针,尾指针 //队列的一个特性 First in first out FIFO int *pFront, *pRear; int op_code; //初始化队列,头指针尾指针此时指向的地址相同 pFront = pRear = mQueue; while (1) { usage(); scanf("%d", &op_code); switch (op_code) { case 1: printf("%p\n", pFront); printf("%d\n", *pFront); InsertData(&pFront, &pRear); break; case 2: DeleteData(&pFront, &pRear); break; case 3: ShowData(&pFront, &pRear); break; default: break; } } return 0; }
好的,以下是用C语言实现队列的加入离开排队的代码注释已经详细标明: ```c #include <stdio.h> #define MAXSIZE 100 // 定义队列最大长度为100 /* 队列结构体 */ typedef struct { int data[MAXSIZE]; // 队列数据 int front; // 队列头部指针 int rear; // 队列尾部指针 } Queue; /* 初始化队列 */ void initQueue(Queue *queue) { queue->front = queue->rear = 0; // 队列头部尾部指针初始化为0 } /* 判断队列是否为空 */ int isEmpty(Queue *queue) { return queue->front == queue->rear; // 如果队列头部尾部指针相等,说明队列为空 } /* 判断队列是否已满 */ int isFull(Queue *queue) { return (queue->rear + 1) % MAXSIZE == queue->front; // 如果队列尾部指针的下一个位置等于队列头部指针,说明队列已满 } /* 入队操作 */ int enqueue(Queue *queue, int data) { if (isFull(queue)) { // 如果队列已满,无法入队 return -1; } queue->data[queue->rear] = data; // 将数据存储到队列尾部指针所指向的位置 queue->rear = (queue->rear + 1) % MAXSIZE; // 队列尾部指针向后移动一位,如果超过了队列最大长度,则回到队列头部 return 0; } /* 出队操作 */ int dequeue(Queue *queue, int *data) { if (isEmpty(queue)) { // 如果队列为空,无法出队 return -1; } *data = queue->data[queue->front]; // 将队列头部指针所指向的数据存储到data中 queue->front = (queue->front + 1) % MAXSIZE; // 队列头部指针向后移动一位,如果超过了队列最大长度,则回到队列头部 return 0; } int main() { Queue queue; initQueue(&queue); // 初始化队列 int data; // 入队操作 enqueue(&queue, 10); enqueue(&queue, 20); enqueue(&queue, 30); // 出队操作 dequeue(&queue, &data); printf("出队数据:%d\n", data); dequeue(&queue, &data); printf("出队数据:%d\n", data); dequeue(&queue, &data); printf("出队数据:%d\n", data); // 再次入队 enqueue(&queue, 40); enqueue(&queue, 50); enqueue(&queue, 60); return 0; } ``` 以上代码实现了一个简单的队列,可以通过 `enqueue` 函数将数据加入队列,通过 `dequeue` 函数将数据从队列中取出。其中,`isEmpty` `isFull` 函数分别用于判断队列是否为空是否已满。在 `enqueue` 函数中,如果队列已满则返回 -1,否则将数据添加到队列尾部指针所指向的位置,并将队列尾部指针向后移动一位。在 `dequeue` 函数中,如果队列为空则返回 -1,否则将队列头部指针所指向的数据存储到参数 `data` 中,并将队列头部指针向后移动一位。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值