数据结构之队列(C语言)

1.队列的定义:

队列(Queue)是一种基础且重要的线性数据结构 ,遵循先进先出(FIFO)​​ 原则,即最早入队的元素最先出队,与栈不同的是出队列的顺序是固定的。队列具有以下特点:

  1. FIFO原则:元素按插入顺序处理,队头(Front)删除,队尾(Rear)插入。
  2. 操作受限:仅允许在两端操作(队尾入队、队头出队),中间元素不可直接访问
  3. 顺序队列(数组实现)​
    • 优点 :内存连续,访问高效。
    • 缺点 :易"假溢出"(数组未满但指针越界),需通过循环队列 优化:
    • 队尾指针循环:rear = (rear + 1) % size
    • 队满条件:(rear + 1) % size == front(牺牲一个存储单元)。
      链式队列(链表实现)​
    • 优点:动态扩容,无固定大小限制

2. 队列的实现:

首先我们打开visual studio,我们需要准备以下界面:

2.1 queue.h代码

其中queue.h主要是存放函数的调用的头文件,内容如下:

c 复制代码
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
#define QDataType int 

struct QueueNode 
{
	QDataType data;
	struct QueueNode* next;//定义 next指针
	//我们可以尝试使用单链表来完成 
};
typedef struct QueueNode QNode;

struct queue
{
	QNode* phead;
	QNode* ptail;
	int size;
	//为什么需要通过结构体来封装两个指针
	//原本需要通过二级指针来完成增加和删除
};
typedef struct queue queue;
//上述完成结构体基本建设

//接下来完成以下接口:
//初始化和销毁
void QueueInit(queue* pq);
void QueueDestroy(queue* pq);

//后增和前删
void QueuePush(queue* pq, QDataType x);
void QueuePop(queue* pq);

//取出之前的数和取出后面的数 
QDataType QueueFront(queue* pq);
QDataType QueueBack(queue* pq);

//返回队列中有效值个数
int QueueSize(queue* pq);

//判空
bool QueueEmpty(queue* pq);

这一块代码是栈的头文件,我们给出接口,接下来我们要尝试在stack.c里面实现这些代码,即这些头文件的接口具体如何实现

1.2 queue.c代码

c 复制代码
#include"queue.h"

void QueueInit(queue* pq)
{
	pq->phead = pq->ptail = NULL;
	pq->size = 0;
}

void QueueDestroy(queue* pq)
{
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pq->phead = pq->ptail = NULL;
}

void QueuePush(queue* pq, QDataType x)
{
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	tmp->data = x;
	tmp->next = NULL;
	if (pq->phead == NULL)
	{
		//如果没有初始化
		pq->phead = tmp;
		pq->ptail = tmp;
		pq->size++;
	}
	else {
		pq->ptail->next = tmp;
		pq->ptail = tmp;
		pq->size++;
	}
}

void QueuePop(queue* pq)
{
	assert(pq);
	QNode* Pop = pq->phead;
	pq->phead = pq->phead->next;
	free(Pop);
	pq->size--;
}

QDataType QueueFront(queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->data;
}

QDataType QueueBack(queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->data;
}

int QueueSize(queue* pq)
{
	assert(pq);
	return pq->size;
}

bool QueueEmpty(queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

我们通过编写依次完成了这些代码的编写。我们接下来测试这些代码是否正常源代码如下:

c 复制代码
#include"queue.h"

void test1(queue* pq)
{
	QueueInit(pq);
	QueuePush(pq,1);
	QueuePop(pq);
	QueuePush(pq, 1);
	QueuePush(pq, 2);
	QueuePush(pq, 3);
	printf("%d ", QueueBack(pq));
	printf("%d ", QueueFront(pq));
	printf("%d",  QueueSize(pq));
	QueueDestroy(pq);
}


int main()
{
	queue q1;
	test1(&q1);
}

尝试利用代码来调试看看我们完成的接口是否有问题:

目前来看是没有问题的。

3 总结:

队列以其严格的FIFO特性和高效的操作,成为管理有序任务的理想工具。理解其实现差异(循环队列 vs 链式队列)和应用场景(调度、缓冲、BFS等),能显著提升系统设计能力。实际开发中需根据数据规模 ​(静态/动态)、性能需求 ​(时间/空间复杂度)和并发环境选择合适的实现方式

相关推荐
笨蛋不要掉眼泪11 分钟前
Java虚拟机:常用参数
java·开发语言·python
happy_0x3f24 分钟前
前端应用的离线暂停更新策略
开发语言·前端·php
shylyly_1 小时前
C++中的类型转换
开发语言·c++·匿名对象·隐式类型转换·拷贝优化
北冥you鱼2 小时前
Go 语言新手扫盲:指针 * 和 & 使用场景详解
开发语言·后端·golang
cui_ruicheng2 小时前
Python数据分析(一):数据分析概述与环境搭建
开发语言·python·数据分析
青山木2 小时前
Hot 100 ---腐烂的橘子
java·数据结构·后端·算法·leetcode·广度优先
未来之窗软件服务2 小时前
计算机考试-快速排序—东方仙盟
数据结构·算法·排序算法·仙盟创梦ide·东方仙盟
心平气和量大福大2 小时前
C#-WPF-UserControl-生命周期(加载 退出)
开发语言·c#·wpf
小龙报2 小时前
【优选算法】1. 水果成蓝 2.找到字符串中所有字母的异位词
java·c语言·数据结构·数据库·c++·redis·算法
wWYy.2 小时前
数据结构:跳表
数据结构