栈和队列的实现

作者:纪念 229日期:2026/6/21

༺ 个人主页 · 纪念229 ༻

🏠我的博客主页🏠

༒专栏目录:《数据结构》༒

༒其它有趣的计算机知识༒

༺世上本没有路,走的人多了自然就有了༻


这篇文章讲述的是用顺序表实现栈、用单链表实现队列,本文主要讲述栈和队列的定义,希望对大家有所帮助!

文章目录

  • 1.Stack.h
  • 2.Stack.c
    • 2.1 STackDesTroy(ST* ps)
    • 2.2STackPush(ST* ps, STDataType x)
    • 2.3 STackEmpty(ST* ps)
    • 2.4 STackPop(ST* ps)
    • 2.5 STacksize(ST* ps)
  • 3.Queue.h
  • 4.Queue.c
    • 4.1QueueInit(Queue* pq)
    • 4.3QueuePush(Queue* pq, QDataType x)
    • 4.4QueueTmpty(Queue* pq)
    • 4.5 QueuePop(Queue* pq)
    • 4.6QueueFront(Queue* pq)
    • 4.7 QueueBack(Queue* pq)
    • 4.8QueueSize(Queue* pq)

1.Stack.h

栈的头文件,讲述程序的功能

代码展示

点我展开

1#pragma once
2#include<stdio.h>
3#include<stdlib.h>
4#include<assert.h>
5#include<stdbool.h>
6
7//定义栈的结构
8typedef int STDataType;
9typedef struct Stack
10{
11  STDataType* arr;
12  int top;
13  int capacity;
14}ST;
15
16//初始化
17void STackInit(ST* ps);
18//销毁
19void STackDesTroy(ST* ps);
20
21//入栈---栈顶
22void STackPush(ST* ps,STDataType x);
23//出栈---栈顶
24void STackPop(ST* ps);
25//取栈顶元素
26STDataType STackTop(ST* ps);
27
28//获取栈中有效元素个数
29int STacksize(ST* ps);
30//栈是否为空
31bool STackEmpty(ST* ps);
32

2.Stack.c

说一下有些函数没有断言,主要讲述重要的地方

2.1 STackDesTroy(ST* ps)

功能:把栈清空
代码展示

1//销毁
2void STackDesTroy(ST* ps)
3{
4  if(ps->arr)
5		free(ps->arr);
6	ps->arr =NULL;
7	ps->capacity = ps->top = 0;
8}
9

我们需要判断栈里是否为空,才能free里的内容

2.2STackPush(ST* ps, STDataType x)

功能:入栈
代码展示

1//入栈---栈顶
2void STackPush(ST* ps, STDataType x)
3{
4	assert(ps);
5	if (ps->capacity == ps->top)
6	{
7	//增容
8		int newcapacity = ps->arr == NULL ? 4 : 2 * ps->capacity;
9		//扩容用realloc,用malloc前面的会消失
10		STDataType* tmp = (STDataType*)realloc(ps->arr,sizeof(STDataType)* newcapacity);
11		if (tmp == NULL) {
12			perror("malloc fial");
13			exit(1);
14		}
15		ps->arr = tmp;
16		ps->capacity =newcapacity;
17	}
18	ps->arr[ps->top++] = x;
19}
20

增容:判断栈是否为空,为空返回4字节否则返回2倍原字节

扩容用realloc不用malloc
原因:malloc是重新启用空间会把原来栈的数据清空

然后给栈赋值,记得更新栈顶和容量

2.3 STackEmpty(ST* ps)

功能:判断栈是否为空
代码展示

1bool STackEmpty(ST* ps)
2{
3 assert(ps);
4 //用top判断栈是否为空
5 return ps->top == 0;
6}
7

要判断一个东西建议用bool类型的函数
判断栈为空就是判断栈顶top是否为0

2.4 STackPop(ST* ps)

功能:出栈

1//出栈---栈顶
2 void STackPop(ST* ps)
3 {
4 //判断栈是否为空
5 assert(!STackEmpty(ps));
6 --ps->top;
7}
8要出栈要判断栈是否为空
9出栈实际上是给栈顶减减
10
11## 2.5 STackTop(ST* ps)
12功能:得到栈顶的元素
13```c
14//取栈顶元素
15 STDataType STackTop(ST* ps)
16 {
17	 //判断栈是否为空
18	 assert(!STackEmpty(ps));
19	 //取的是ps->arr[ps->top - 1](栈顶的元素)而不是栈顶数
20	 return ps->arr[ps->top - 1];
21}
22

既然要取栈顶元素就要判断栈是否为空
直接返回栈顶元素即可(返回的下标是top - 1)

2.5 STacksize(ST* ps)

功能:获取栈中存储的有效个数
代码展示

1//获取栈中有效元素个数
2 int STacksize(ST* ps)
3 {
4 assert(ps);
5 return ps->top;
6}
7

栈中的有效个数就是栈顶的值


3.Queue.h

展示函数功能
代码展示

点我展开

1#pragma once
2#include<stdio.h>
3#include<stdlib.h>
4#include<assert.h>
5#include<stdbool.h>
6
7typedef int QDataType;
8//队列节点的结构
9typedef struct queueNode
10{
11  QDataType val;
12  struct queueNode* next;
13  //
14}QueueNode;
15//队列的结构
16typedef struct queue
17{
18  QueueNode* phead;
19  QueueNode* ptail;
20  //int size;//队列中有效数据的个数
21}Queue;
22
23//初始化
24void QueueInit(Queue* pq);
25//销毁队列
26void QueueDesTroy(Queue* pq);
27
28//入队——队尾
29void QueuePush(Queue* pq, QDataType x);
30
31
32//出队——队头
33void QueuePop(Queue* pq);
34//队列判空
35bool QueueTmpty(Queue* pq);
36//队列有效元素个数
37int QueueSize(Queue* pq);
38
39//取队头数据
40QDataType QueueFront(Queue* pq);
41//取队尾数据
42QDataType QueueBack(Queue* pq);
43

>队列是由两个指针组成的结构体,包括头phead和尾ptail >队列里是单链表组成的 ```

4.Queue.c

实现队列功能

4.1QueueInit(Queue* pq)

功能:初始化队列
代码展示

1
2//初始化
3void QueueInit(Queue* pq)
4{
5	assert(pq);
6	pq->phead = pq->ptail = NULL;
7}
8
9
10把头尾指针置空
11
12##  4.2QueueDesTroy(Queue* pq)
13
14功能:销毁队列里的数据
15代码展示
16```c
17//销毁队列
18void QueueDesTroy(Queue* pq)
19{
20	assert(pq);
21	QueueNode* pcur = pq->phead;
22	while (pcur)
23	{
24		QueueNode* next = pcur->next;
25		free(pcur);
26		pcur = next;
27	}
28	pq->phead = pq->ptail = NULL;
29}
30

给个next保存下一位的地址完成节点的销毁
最后给头指针和尾指针置空

4.3QueuePush(Queue* pq, QDataType x)

功能:入队(尾入队)
代码展示

1//入队——队尾
2void QueuePush(Queue* pq, QDataType x)
3{
4	assert(pq);
5	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
6	if (newnode == NULL)
7	{
8		perror("malloc fial");
9		exit(1);
10	}
11	newnode->val = x;
12	newnode->next = NULL;
13	//队列为空
14	if (pq->phead == NULL) {
15		pq->phead = pq->ptail = newnode;
16	}
17	else {
18		pq->ptail->next = newnode;
19		pq->ptail = newnode;
20	}
21	//ps->size++;
22}
23

每次入队都创建一个节点把val赋好next指向NULL
如果队列为空就把头指针(phead)和尾指针(ptail)被赋值为newnode指针,若不是就把尾指针指向newnode再把ptail赋值为newnode指针

4.4QueueTmpty(Queue* pq)

功能:判断队列是否为空
代码展示

1//队列判空
2bool QueueTmpty(Queue* pq)
3{
4	assert(pq);
5	return pq->phead == NULL;
6}
7

判断队列为空就是看头指针是否等于NULL

4.5 QueuePop(Queue* pq)

功能:出队(头指针chu队列)
代码展示

1//出队——队头
2void QueuePop(Queue* pq)
3{
4	assert(!QueueTmpty(pq));
5	//只有一个节点,phead-ptai都置为空
6	if (pq->phead == pq->ptail)
7	{
8		free(pq->phead);
9		pq->phead = pq->ptail = NULL;
10	}
11	else {
12		QueueNode* next = pq->phead->next;
13		free(pq->phead);
14		pq->phead = next;
15	}
16	//pq->size--;
17}
18

要出队列先判断队列是否为空
如果只有一个节点就free头结点后置空
不是则给个next指针(找到新的头结点)然后free(phead),把phead赋值为next

4.6QueueFront(Queue* pq)

功能:获取队头信息
代码展示

1//取对头数据
2QDataType QueueFront(Queue* pq)
3{
4//队列判空
5 assert(!QueueTmpty(pq));
6 return pq->phead->val;
7}
8

判断队列是否为空,然后返回对头数据

4.7 QueueBack(Queue* pq)

功能:获取队尾信息
代码展示

1//取队尾数据
2QDataType QueueBack(Queue* pq)
3{
4//队列判空
5	assert(!QueueTmpty(pq));
6	return pq->ptail->val;
7}
8

判断队列是否为空,返回队尾数据

4.8QueueSize(Queue* pq)

功能:获取队列有多少有效数据
方案1.
把队列多加int size,当出队入队是加加减减(前面代码有注释)

具体代码在方案2中也有注释

方案2.
遍历队列返回有效个数
代码展示

1//队列有效元素个数
2int QueueSize(Queue* pq)
3{
4	assert(pq);
5	//第一种方案遍历链表——适用于不会频繁调用队列有效个数的场景
6	QueueNode* pcur = pq->phead;
7	int size = 0;
8	while (pcur)
9	{
10		++size;
11		pcur = pcur->next;
12	}
13	return size;
14
15	//第二种方式:遍历链表——适用于频繁调用有效数据的场景
16	//return pq->size;
17}
18

方案1适用于不常调用有效个数的情况
方案2适用于常调用有效个数的情况

这篇文章在这里就结束了,希望对你有所帮助!


栈和队列的实现》 是转载文章,点击查看原文


相关推荐


【云计算】华为公有云构建高可用Redis集群
Harvy_没救了2026/6/13

华为公有云构建高可用Redis集群(3主3从 + AS弹性扩容)详细方案 一、方案概述 本方案基于华为云服务(ECS、VPC、AS、IMS、ELB),手动搭建一个 Redis Cluster(3主3从),并通过 弹性伸缩AS 实现自动扩容(增加节点),但不配置自动缩容。扩容时新节点自动加入集群,并通过脚本完成集群拓扑更新。整体架构满足 高可用、负载均衡、水平扩展 的需求。 核心技术栈 服务作用VPC + 安全组隔离网络,保证内网互通ECS运行Redis服务的云服务器(6台基础节点)IMS


从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮)三角洲自动跑刀教程
深度学习教程,2026/6/6

从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮 从零实现《三角洲行动》手游自动跑刀脚本:ADB 直控 + OpenCV 视觉识别 + 固定点位搜刮一、前言二、整体架构与技术栈三、ADB 控制层:截图、点击、滑动四、核心难点一:怎么判断"真进游戏了"?五、核心难点二:识别"这把刷在哪个出生点"5.1 用圆检测把小地图"圆形抠出来"5.2 模板匹配识别出生点 六、核心难点三:自动拾取物资七、把它串起来:固定路线八、一个诚实的工程结论九、


React Native + RNOH:跨页面数据回传的最佳实践与避坑指南
皮蛋小精灵2026/5/31

从内存闭包到官方路由通信的深度对比 技术栈: React Native 0.77 + React Navigation v7 + RNOH(React Native OpenHarmony) 适用场景: 表单录入、列表选择器、跨页面数据回传通信 一句话结论: 内存闭包 Bridge 体验虽好但存在“热重载失效、系统回收丢回调、嵌套覆盖”三大致命缺陷;官方 route.params 需配合 setParams 清洗;在嵌套/鸿蒙 JS Stack 下,使用 CommonActions.setPa


aardio从惊喜到失望到被拉黑二三事
1681692026/5/9

aardio从惊喜到失望到被拉黑二三事 前情 其实我非常喜欢开发一些小工具,用于解决工作中和生活中的问题,我个人也有开发一些小程序和一些cli,但是对于桌面端一直没的找到好的开发方案,其中有试过autohotkey,但是它的语法和学习资料非常少,带你开发GUI就更少了,平时也就用用热词热键什么的,electron我也用过,但是它太重了,一直想找一个轻量点的,我也知道c#开发桌面工具非常不错,但是那要重新学一门语言,有想过学,但是一看c#教程就犯困也就没什么尝试了,直到某一天看到了aardio,真


一觉醒来,大模型就帮我排查完页面性能问题
candyTong2026/4/29

最近遇到一个性能问题,我让大模型自己去处理,然后就去午休了,醒来之后,它还真的把问题找出来并修复了 先说结果 最终定位出来的根因是: 这个业务工作台的查询表单,把 Formily 的 form 实例塞进了带 devtools 的 Zustand store。 这件事在开发环境里会非常要命,因为 form 不是一个轻量对象,它里面带着大量字段状态、reaction、effect、schema 和联动信息。 一旦进了 store,又被 devtools 观察、快照、序列化,内存就会被瞬间放大。


打造工业级全栈文件管理器:深度解析上传、回收站与三重下载流控技术
微特尔普拉斯2026/4/20

在构建企业级 Web 应用时,文件管理器是一个看似简单实则充满挑战的模块。面对大文件上传卡顿、大文件下载导致浏览器崩溃、以及误删不可恢复等痛点,我们需要一套更科学的架构方案。 本文将通过 Vue 2/3 + Spring Boot 的组合,详细拆解如何实现一套具备:排重检测、多线程后台下载、流式下载进度监控、以及回收站机制的文件管理系统。 一、 核心技术原理分析 1. 智能冲突检测上传 在上传文件前,系统会先发起一个“预检请求”(Check Exists)。 原理:前端获取文件名


一文搞懂Harness Engineering与Meta-Harness
GreenTea2026/4/12

一、什么是Harness Engineering harness engineering目前没有官方的英文翻译,但是我认为“驾驭工程”非常合适。“驾驭”一词本身有两层含义,“释放”与“约束”这两个相辅相成的维度,打个形象的比方,跟古代君臣关系一样,既要委以重任,又要设立制衡。 我们可以将这两层含义拆解如下: 1.1 释放潜力:让 AI 像工程师一样“真刀真枪”地干活 把模型放到现场,赋予了工程现场的实权,像一个工程师一样干活,能够接触代码库、执行命令,释放模型的潜力 传统的 Copilot


大模型应用开发学习第一天
程序员雷欧2026/4/4

从今天开始,雷欧将和大家一起学习大模型应用开发。我们不搞基础,不搞虚的,只搞最重要的知识来学习。         今天,我们要学习的是Transformer架构!!当然,底层机理,包括代码实现,并不需要我们知道,那么,我们需要学会什么呢?咱接着往下看……         首先,简单介绍一下什么是Transformer,Transformer是一种基于纯注意力机制的神经网络架构,由谷歌在2017年提出,最初用于机器翻译任务,现在已成为NLP和CV领域的基础架构。 1.Transformer整


腾讯云WorkBuddy实战, 全场景智能体工作搭子,这只龙虾真能帮你干活吗
不惑_2026/3/26

全网都在养虾。 朋友圈被刷屏了。同事也在搞。连高盛的分析师都惊了,说中国人接受AI的速度令人震惊。 但说实话,在我真正装上WorkBuddy之前,我是持怀疑态度的。 之前OpenClaw火的时候,很多人的真实体验是,折腾三小时,报错二十次,连命令行都没跑起来。一个面向普通人的AI工具,如果连安装都搞不定,那跟没有有什么区别? 所以当腾讯说WorkBuddy零部署、下载就能用的时候, 我第一反应是,真的假的。 ▲ WorkBuddy桌面端主界面,打开就是一个对话框,简洁到有点不像腾讯的风格 装上


JavaScript 中 Map 的完整解析
小李子呢02112026/3/18

Map 是 ES6 新增的键值对集合类型,专门用于解决普通对象({})作为键值存储的痛点(比如键只能是字符串 / 符号、无法直接获取长度等)。 1. 核心特性 特性说明键的类型可以是任意类型(数字、字符串、布尔值、对象、函数、null/undefined)遍历顺序严格按照插入顺序遍历(普通对象不保证)长度获取直接通过 map.size 获取(普通对象需手动计算 Object.keys(obj).length)键的唯一性同一个键只能存一个值(重复设值会覆盖)内存 / 性能存储大量键值对时,Ma

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 聚合阅读