当前位置: 首页 > news >正文

从 0 到 1 学 C 语言队列:链表底层实现(初始化 / 入队 / 出队 / 销毁),代码可直接复用!

队列

1 概念和结构

概念:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
队列关键操作说明:

  • ⼊队列:进⾏插⼊操作的⼀端称为队尾
  • 出队列:进⾏删除操作的⼀端称为队头
    在这里插入图片描述
    队列的底层结构选择
    队列的底层既可以用链表也可以用数组实现,但链表的结构实现更优,数组的结构出队列数组的整体元素要向前挪动一位,效率会非常低

小提醒:如果对链表不熟悉的可以点击链表

2 队列Queue的实现
2.1 队列头文件Queue.h的初始设置
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
//队列结点结构
typedef struct QueueNode
{int val;struct QueueNode* next;
}QNode;
//队列结构
typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;

使用typedef重命名数据类型typedef int QDataType使代码具有可扩展性,如果数据类型变化的话直接修改这条typedef语句就行了。队列Queue的底层是用链表来进行实现,而链表是用一个个结点QNode实现。由于队列Queue对只对其前后末端位置操作,为了方便找到链表的最后一个元素而不用再从头结点遍历,我们使用一个ptail指针指向链表尾部。并用size记录链表的大小。

2.2 队列的初始化
void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}

pq->phead = pq->ptail = NULL头指针和尾指针都置为NULL,并将size也赋值为0

2.3 入队列

在此之前先要说明判断队列非空的QueueEmpty函数

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

如果队列中size=0即没有元素则队列为空。

入队列完整实现:

void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc failed!");exit(1);}newnode->val = x;newnode->next = NULL;if (QueueEmpty(pq)){pq->ptail = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->phead = pq->ptail->next;}pq->size++;
}

第一部分:
malloc函数创造结点,并将结点初始化

	QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc failed!");exit(1);}newnode->val = x;newnode->next = NULL;

第二部分:
由于队列的底层仍然是链表,所以插入要分为链表为空和链表非空两种情况(用QueueEmpty(pq)函数判断链表是否为空)

	if (QueueEmpty(pq)){pq->ptail = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->phead = pq->ptail->next;}

第三部分:
将队列的size++

pq->size++;
2.4 出队列
void QueuePop(Queue* pq)
{assert(!QueueEmpty(pq));QNode* temp = pq->phead;pq->phead = pq->phead->next;free(temp);if (pq->phead == NULL){pq->ptail = NULL;}pq->size--;
}

第一部分:
出队列首先要用QueueEmpty函数判断队列是否为空

assert(!QueueEmpty(pq));

第二部分:
将队列头原位置赋值给temp,再将头结点移动到下一个结点,并将temp指向空间释放。

QNode* temp = pq->phead;
pq->phead = pq->phead->next;
free(temp);

第三部分:
如果将最后一个元素出栈了即phead=NULL,则此时也应该改变tailNULL,并最后将size--

if (pq->phead == NULL)
{pq->ptail = NULL;
}
pq->size--;
2.5 取队头元素
QDataType QueueFront(Queue* pq)
{assert(!QueueEmpty(pq));return pq->phead->val;
}

首先判断队列非空,将头节点phead指向的元素val返回就可以了

2.6 取队尾元素
QDataType QueueBack(Queue* pq)
{assert(!QueueEmpty(pq));return pq->ptail->val;
}

首先判断队列非空,将尾节点ptail指向的元素val返回就可以了

2.7 队列有效数据元素个数
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}

size就是队列的有效元素个数

2.8 销毁队列
void QueueDestroy(Queue* pq)
{assert(pq);QNode* pcur = NULL;while (pq->phead != NULL){pcur = pq->phead;pq->phead = pq->phead->next;free(pcur);}pq->phead = pq->ptail = NULL;pq->size = 0;
}

当指针pq->phead不为NULL时,一直向后遍历,pcur记录当前头节点phead的地址,而phead指向它的下一个位置,free(pcur)将先前头节点phead指向位置空间释放,最后pq->phead = pq->ptail = NULL将头结点phead和尾节点ptail都赋值为NULL,并将size置为0

http://www.dtcms.com/a/503599.html

相关文章:

  • 书店网站建设网站栏目结构软文营销的特点有哪些
  • 做个网站要多久做网站app要多少钱
  • 1. Linux 驱动开发前景
  • 深入理解进程生命周期:从 fork 到 exit 的完整旅程
  • 英维克(002837)-2025-10-19
  • 自助手机网站建站软件wordpress metaslider
  • PCIe协议之 Equalization篇 之 FIR 三抽头的三因子的理解
  • FFmpeg 基本API av_seek_frame函数内部调用流程分析
  • FFmpeg 基本API avcodec_send_packet函数内部调用流程分析
  • 手机建站网站常德营销型网站建设
  • Flutter 与原生混合编程
  • DevOps 与 部署入门:加速软件交付与运维的实践指南
  • 优化网站seo中山做百度网站的公司名称
  • 上海袜网站建设电商营业执照
  • 找到K个最接近的元素
  • Java中JDK、JRE、JVM概念
  • MySQL 表操作核心指南:CRUD 与进阶技巧
  • 网站开发个人总结网页设计与网站建设在线考试1
  • 算法笔记 05
  • 游戏科技网站杭州建设工程交易中心网站
  • 网站做推广要备案吗四川seo快速排名
  • 有关房地产开发建设的网站哪些网站可以接点私活做的
  • 有关应广单片机数据类型与ROM空间优化的一点看法
  • 【2026计算机毕业设计】基于Jsp的医疗设备及业务综合巡检系统
  • 个人业务技能提升如何助力:从“做事”到“成事”的跃迁之路
  • 我们需要的中文编程是什么样子的?
  • 那些网站可以接私活做做兼职有哪些网站
  • 绚星智慧科技斩获智享会三项大奖,领跑AI时代学习与发展赛道
  • 零基础入门Java·基础篇 学习大纲
  • XSS 攻击详解:原理、类型与防范策略