news 2026/4/23 20:48:46

C语言:栈和队列

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言:栈和队列

文章目录

    • 前言
  • 1. 栈
    • 1.1 栈的概念及结构
    • 1.2 栈的实现
    • 1.3 栈的C语言实现
      • 1.3.1 stack.h
      • 1.3.2 stack.c
      • 1.3.3 test.c
  • 2. 队列
    • 2.1 队列的概念及结构
    • 2.2 队列的实现
      • 2.2.1 Queue.h
      • 2.2.2 Queue.c
      • 2.2.3 test.c

前言

栈(先进后出)和队列(先进先出)是逻辑结构(描述数据的组织和操作规则),他们可以用顺序表(数组)、链表等存储结构(描述数据在内存中的存储方式)实现。

1. 栈

这里我将说明什么是栈和如何用C语言表示栈

1.1 栈的概念及结构

接下来引用两张图片:

1.2 栈的实现


1.3 栈的C语言实现

最主要的还是如何用C语言实现栈,我们将代码分别分为stack.h , stack.c , 和 test.c ,这里用动态顺序表实现。

1.3.1 stack.h

代码展示:

#pragmaonce#include<stdio.h>#include<stdlib.h>#include<stdbool.h>#include<assert.h>typedefintSTDataType;typedefstructStack{STDataType*a;inttop;intcapacity;}ST//初始化和销毁voidSTInit(ST*pst);voidSTDestroy(ST*pst);//插入,入栈voidSTPush(ST*pst,STDataType x);//删除,出栈voidSTPop(ST*pst);//获取栈顶数据STDataTypeSTTop(ST*pst);//判空boolSTEmpty(ST*pst);//intSTSize(ST*pst);
  • STDataType* a:动态数组的 “容器”,存储栈的实际数据,区别于静态栈的固定数组;
  • int top:栈的 “位置标记”,记录栈顶的位置,是入栈 / 出栈的核心依据(注意初始值定义);
  • int capacity:栈的 “容量上限”,跟踪动态数组的总大小,用于判断是否需要扩容,避免越界

1.3.2 stack.c

代码实现:

#include"stack.h"voidSTInit(ST*pst){assert(pst);pst->a=NULL;pst->capacity=0;//top指向栈顶下一个元素pst->top=0;}voidSTDestroy(ST*pst){assert(pst);free(pst->a);pst->a=NULL;pst->capacity=pst->top=0;}//插入,入栈voidSTPush(ST*pst,STDataType x){assert(pst);if(pst->top==pst->capacity){intnewcapacity=pst->capacity==0?4:pst->capacity*2;STDataType*tmp=(STDataType*)realloc(pst->a,newcapacity*sizeof(STDataType));if(tmp==NULL){perror("realloc fail");return;}pst->a=tmp;pst->capacity=newcapacity;}pst->a[pst->top]=x;pst->top++;}//删除,出栈voidSTPop(ST*pst){assert(pst);pst->top--;}//获取栈顶数据STDataTypeSTTop(ST*pst){assert(pst);assert(pst->top>0);returnpst->a[pst->top-1];}//判空boolSTEmpty(ST*pst){assert(pst);returnpst->top==0;}//intSTSize(ST*pst){assert(pst);returnpst->top;}

这里较为复杂的是入栈void STPush(ST* pst, STDataType x),需判断内存够不够,再按需扩容!

1.3.3 test.c

#include"stack.h"intmain(){ST s;STInit(&s);STPush(&s,1);STPush(&s,2);STPush(&s,3);while(!STEmpty(&s)){printf("%d\n",STTop(&s));STPop(&s);}STDestroy(&s);return0;}

这里我只是随便测试一下,大家可以按自己的想法测试。

2. 队列

2.1 队列的概念及结构

2.2 队列的实现


这里依旧把代码分为Queue.h , Queue.c , test.c 三部分。

2.2.1 Queue.h

#pragmaonce#define_CRT_SECURE_NO_WARNINGS// 链式结构:表示队列#pragmaonce#include<stdbool.h>#include<stdio.h>#include<stdlib.h>#include<assert.h>typedefintQDataType;typedefstructQListNode{structQListNode*next;QDataType data;}QNode;// 队列的结构typedefstructQueue{QNode*phead;QNode*ptail;intsize;}Queue;// 初始化队列voidQueueInit(Queue*q);// 队尾入队列voidQueuePush(Queue*q,QDataType data);// 队头出队列voidQueuePop(Queue*q);// 获取队列头部元素QDataTypeQueueFront(Queue*q);// 获取队列队尾元素QDataTypeQueueBack(Queue*q);// 获取队列中有效元素个数intQueueSize(Queue*q);// 检测队列是否为空,如果为空返回非零结果,如果非空返回0intQueueEmpty(Queue*q);// 销毁队列voidQueueDestroy(Queue*q);
  • QNode是链式队列的数据载体:每个节点存一个数据 + 下一个节点的指针,串联成链表;
  • Queue是链式队列的管理核心:phead/ptail直接定位头尾,保证入队 / 出队O(1)效率,size快速统计节点数;
  • 链式队列的优势:动态扩容(无容量上限)、无 “假溢出”(区别于顺序队列的循环数组),是实际开发中队列的主流实现方式。
  • size可直接计算链表结点个数

2.2.2 Queue.c

#define_CRT_SECURE_NO_WARNINGS#include"Queue.h"voidQueueInit(Queue*q){assert(q);q->phead=NULL;q->ptail=NULL;q->size=0;}// 队尾入队列voidQueuePush(Queue*q,QDataType data){QNode*node=(QNode*)malloc(sizeof(QNode));if(node==NULL){perror("malloc fail");return;}node->next=NULL;node->data=data;if(q->phead==NULL){q->phead=node;q->ptail=node;}else{q->ptail->next=node;q->ptail=node;}q->size++;}// 队头出队列voidQueuePop(Queue*q){assert(q);assert(q->size!=0);QNode*m=q->phead->next;if(q->phead==q->ptail)q->ptail=NULL;free(q->phead);q->phead=m;q->size--;}//// 获取队列头部元素QDataTypeQueueFront(Queue*q){assert(q);returnq->phead->data;}//// 获取队列队尾元素QDataTypeQueueBack(Queue*q){assert(q);returnq->ptail->data;}//// 获取队列中有效元素个数intQueueSize(Queue*q){returnq->size;}//// 检测队列是否为空,如果为空返回非零结果,如果非空返回0intQueueEmpty(Queue*q){if(q->phead!=NULL){return0;}return1;}//// 销毁队列voidQueueDestroy(Queue*q){assert(q);QNode*node=q->phead;while(node){QNode*next=node->next;free(node);node=next;}q->phead=q->ptail=NULL;q->size=0;}

2.2.3 test.c

#include"Queue.h"intmain(){Queue q;QueueInit(&q);QueuePush(&q,1);QueuePush(&q,2);QueuePush(&q,3);QueuePush(&q,4);while(!QueueEmpty(&q)){printf("%d ",QueueFront(&q));QueuePop(&q);}return0;}

大家可刷题熟悉这两种逻辑结构😄

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 9:57:16

Windows:win10系统,底层任务栏显示空白图标

一、情况描述1、随便打开一个文件夹&#xff0c;点击“查看”菜单&#xff0c;勾选“隐藏的项目”。2、快捷键 【WinR】&#xff0c;在打开的运行窗口中输入 【%localappdata%】&#xff0c;回车。3、在打开的文件夹中&#xff0c;找到 【Iconcache.db】&#xff0c;将其删除。…

作者头像 李华
网站建设 2026/4/23 9:59:33

【信创】华为昇腾大模型部署

一、系统与硬件环境说明模块说明CPU鲲鹏 920 / 930 系列&#xff08;ARM64架构&#xff09;GPU/NPU华为昇腾 910B2 2&#xff08;支持BF16、INT8量化&#xff09;内存≥ 256GB存储≥ 2TB SSD操作系统openEuler / 麒麟 / 统信UOS&#xff08;国产信创OS&#xff09;驱动CANN ≥…

作者头像 李华
网站建设 2026/4/23 12:08:51

UART、USART、LPUART:原理差异与实战应用

目录 一、核心定义与核心差异&#xff08;先理清 “是什么”&#xff09; 二、原理详解&#xff08;从基础到特化&#xff09; 1. UART 核心原理&#xff08;异步串行通信&#xff0c;三者的基础&#xff09; &#xff08;1&#xff09;UART 帧结构&#xff08;异步通信的核…

作者头像 李华
网站建设 2026/4/23 9:57:48

Java程序员如何高效阅读开源框架源码?

今天看到了一位博主分享自己阅读开源框架源码的心得&#xff0c;看了之后也引发了我的一些深度思考。我们为什么要看源码&#xff1f;我们该怎么样去看源码&#xff1f; 其中前者那位博主描述的我觉得很全了&#xff08;如下图所示&#xff09;&#xff0c;就不做过多的赘述了&…

作者头像 李华
网站建设 2026/4/23 13:18:00

普通Java程序员如何成为性能调优大神?

性能优化可以说是很多一线大厂对其公司内高级开发的基本要求&#xff08;其中以Java岗最为显著&#xff09;。其原因有两个&#xff1a;一是提高系统的性能&#xff0c;二是为公司节省资源。两者都能做到&#xff0c;那你就不可谓不是普通程序员眼中的“调优大神了”。那么如何…

作者头像 李华