【数据结构(C语言)】浅谈栈和队列

目录
文章目录
前言
一、栈
1.1 栈的概念及结构
1.2 栈的实现
1.2.1. 支持动态增长的栈的结构
1.2.2 初始化栈
1.2.3 入栈
1.2.4 出栈
1.2.5 获取栈顶元素
1.2.6 获取栈中有效元素个数
1.2.7 检查栈是否为空
1.2.8 销毁栈
二、队列
2.1 队列的概念及结构
2.2 队列的实现
2.2.1 队列的结构
2.2.2 初始化队列
2.2.3 入队
2.2.4 出队
2.2.5 获取队头元素
2.2.6 获取队尾元素
2.2.7 获取队列中有效元素个数
2.2.8 检查队列是否为空
2.2.9 销毁队列
总结
一、栈
1.1 栈的概念及结构
栈(Stack)是一种线性数据结构,它可以看作是一种特殊的列表。栈只能在一端进行插入和删除操作,这一端被称为栈顶(Top)。栈按照后进先出(LIFO, Last In First Out)的原则进行操作,即最后一个进栈的元素最先被弹出。栈可以用数组或链表实现。栈的主要操作包括压栈(进栈/入栈)(Push)和弹栈(出栈)(Pop),还有取栈顶元素(Top)和判断栈是否为空(Empty)等。栈在编程中常用于函数调用、表达式求值、括号匹配等场景。

1.2 栈的实现
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。所以我们这里使用数组实现栈。用数组实现也分为静态的和动态的,静态的实际中一般不实用,所以我们实现动态的。
1.2.1. 支持动态增长的栈的结构
这里我们声明一个结构体,一个成员为指针a,用来存放开辟空间的首地址(即动态数组),一个成员top用来存放栈顶位置,还有一个成员capacity用来存放开辟的空间大小,方便数组扩容。
代码如下:
typedef int StDataType;typedef struct Stack
{StDataType* a;int top; // 标识栈顶位置的int capacity;
}St;
1.2.2 初始化栈
将结构体中的指针a赋值为NULL,将capacity赋值为0,将top赋值为0,表示top指向栈顶元素的下一个位置(也可以赋值为-1,表示top指向栈顶元素,这里我们使用第一种)。
代码如下:
void StInit(St* pst)
{assert(pst);pst->a = NULL;pst->capacity = 0;//表示top指向栈顶元素的下一个位置pst->top = 0;//表示top指向栈顶元素,如果为-1,后面的代码也要改//pst->top = -1;
}
1.2.3 入栈
入栈之前要先判断开辟的空间满了没,如果满了,可以使用realloc()函数重新分配数组大小,然后再将元素插入top所指向的位置,最后将top+1。
代码如下:
void StPush(St* pst, StDataType x)
{assert(pst);if (pst->top == pst->capacity){int newCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;StDataType* tmp = (StDataType*)realloc(pst->a, newCapacity * sizeof(StDataType));if (tmp == NULL){perror("realloc fail");exit(-1);}pst->a = tmp;pst->capacity = newCapacity;}pst->a[pst->top] = x;pst->top++;
}
1.2.4 出栈
先要确保栈中有元素,可以使用断言,如果有,则只需要top-1就行。
代码如下:
void StPop(St* pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}
1.2.5 获取栈顶元素
先确保栈中有元素,然后直接返回top-1所指向位置的元素即可。
代码如下:
StDataType StTop(St* pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}
1.2.6 获取栈中有效元素个数
因为top指向栈顶元素的下一个位置,其大小刚好为元素的个数,所以直接返回top即可。
代码如下:
int StSize(St* pst)
{assert(pst);return pst->top;
}
1.2.7 检查栈是否为空
判断top是否为0,为0即为空。
代码如下:
bool StEmpty(St* pst)
{assert(pst);return pst->top == 0;
}
1.2.8 销毁栈
先将动态分配的内存释放了,再将结构体中的成员赋值为初始化栈时所赋值的值就行。
代码如下:
void StDestroy(St* pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = 0;pst->capacity = 0;
}
二、队列
2.1 队列的概念及结构
队列(Queue)是一种遵循先进先出(First In First Out,FIFO)原则的数据结构,即最先插入队列的元素最先被取出。队列具有两个端点,一个是队头(Head),一个是队尾(Tail),入队操作(enqueue)在队尾进行,出队操作(dequeue)在队头进行。队列的应用领域很广,例如实现任务调度、消息传递、缓冲区等。常见队列的实现包括:单向队列、双向队列和循环队列等。我们这里主要讨论单向队列。

2.2 队列的实现
我们这里实现的是最基础的单向队列,双向队列和循环队列各位读者可另行了解。队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低(因为要整体把元素往前移,时间复杂度为O(n),虽然在算法中用数组模拟实现队列可以使用头尾双指针使时间复杂度变成O(1),但这样做出队的同时也把空间浪费了)。
2.2.1 队列的结构
因为使用链表实现队列,所以先声明一个队列的结点的结构体,其成员跟链表的声明一致,有两个成员,一个为数据val,另一个为next指针。然后为了后面实现的方便,再声明一个队列结构体,其成员包括队头指针phead和队尾指针ptail以及一个记录队列大小的整形size。
代码如下:
typedef int QDataType;typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;
2.2.2 初始化队列
将队头指针phead和队尾指针ptail赋值为NULL,将size赋值为0。
代码如下:
void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}
2.2.3 入队
先动态申请一个新结点,将要入队的元素赋给新结点的val,再将新结点的next指针指向NULL。然后判断这个队列是否为空,如果为空,则将队头指针phead和队尾指针ptail都指向新结点;如果不为空,则只要改变队尾指针ptail就行,即先将队尾指针ptail指向的结点的next指针指向新结点,再将队尾指针ptail指向新结点。最后将size+1就行了。
代码如下:
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newNode = (QNode*)malloc(sizeof(QNode));if (newNode == NULL){perror("malloc fail");exit(-1);}newNode->val = x;newNode->next = NULL;if (pq->phead == NULL){pq->phead = pq->ptail = newNode;}else{pq->ptail->next = newNode;pq->ptail = newNode;}pq->size++;
}
2.2.4 出队
先要确保队列中有结点,可以使用断言。然后再判断队列中是否只有一个结点,如果是,则释放这个结点后,要将队头指针phead和队尾指针ptail都指向NULL;如果不是,则只需要将队头指针phead指向它所指向的结点的下一个结点,并将它原来所指向的结点释放就行。最后将size-1。
代码如下:
void QueuePop(Queue* pq)
{assert(pq);assert(pq->phead);if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}else{QNode* tmp = pq->phead;pq->phead = pq->phead->next;free(tmp);}pq->size--;
}
2.2.5 获取队头元素
先确保队列有结点,再返回队头指针phead所指向的结点的值val。
代码如下:
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
2.2.6 获取队尾元素
先确保队列有结点,再返回队尾指针ptail所指向的结点的值val。
代码如下:
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}
2.2.7 获取队列中有效元素个数
直接返回size。
代码如下:
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
2.2.8 检查队列是否为空
判断队头指针phead是否为NULL。
代码如下:
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}
2.2.9 销毁队列
先遍历释放队列中的每一个结点,再将队列结构体中的成员赋值为初始化队列时所赋值的值就行。
代码如下:
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
总结
以上就是关于栈和队列的基本概念和操作。通过这篇文章,希望大家能够更好地理解关于栈和队列的原理和实现,并在实际编程中灵活运用它们。
相关文章:
【数据结构(C语言)】浅谈栈和队列
目录 文章目录 前言 一、栈 1.1 栈的概念及结构 1.2 栈的实现 1.2.1. 支持动态增长的栈的结构 1.2.2 初始化栈 1.2.3 入栈 1.2.4 出栈 1.2.5 获取栈顶元素 1.2.6 获取栈中有效元素个数 1.2.7 检查栈是否为空 1.2.8 销毁栈 二、队列 2.1 队列的概念及结构 2.2 队…...
【NGINX--5】身份验证
1、HTTP 基本身份验证 需要通过 HTTP 基本身份验证保护应用或内容。 生成以下格式的文件,其中的密码使用某个受支持的格式进行了加密或哈希处理: # comment name1:password1 name2:password2:comment name3:password3第一个字段是用户名࿰…...
【网络奇缘】- 计算机网络|分层结构|ISO模型
🌈个人主页: Aileen_0v0🔥系列专栏: 一见倾心,再见倾城 --- 计算机网络~💫个人格言:"没有罗马,那就自己创造罗马~" 目录 计算机网络分层结构 OSI参考模型 OSI模型起源 失败原因: OSI模型组成 协议的作用 📝全文…...
使用whisper实现语音转文本
项目地址:GitHub - openai/whisper: Robust Speech Recognition via Large-Scale Weak Supervision 1、需要py3.8环境 conda activate p38 2、安装 pip install -U openai-whisper 3、下载项目 pip install githttps://github.com/openai/whisper.git 4、安装…...
Django中间件与csrf
一. django中间件 1. 什么是django中间件 # django中间件是django的门户1. 请求来的时候需要先经过中间件才能到达真正的django后端2. 响应走的时候最后也需要经过中间件才能发送出去 2. django中间件的个数 django自带七个中间件, 分别是SecurityMiddleware, SessionMiddle…...
【搜维尔科技】产品推荐:Virtuose 6D RV,大型工作空间触觉设备
Virtuose 6D RV为一款具有大工作空间并在所有6自由度上提供力反馈的触觉设备,设计专用于虚拟现实环境,特别适合于大型虚拟物体的处理。 Virtuose 6D RV是当今市场上唯一将高工作效率与高工作量相结合在一起的产品。6D RV特别适合于缩放与操纵等应用&…...
<JavaEE> 什么是线程(Thread)?进程和线程有什么区别?
目录 一、线程(Thread)的概念 二、线程存在的意义 2.1 并发编程 2.2 比进程更“轻量” 三、使用线程时应该注意 四、进程和线程的区别 五、Java中的线程和操作系统中的线程是不同的概念 六、多线程编程 一、线程(Thread)的…...
【赠书第7期】从零基础到精通Flutter开发
文章目录 前言 1 安装Flutter和Dart 2 了解Flutter的基础概念 2.1 Widget 2.2 MaterialApp和Scaffold 2.3 Hot Reload 3 编写你的第一个Flutter应用 3.1 创建一个Flutter项目 3.2 修改默认页面 3.3 添加交互 4 深入学习Flutter高级特性 4.1 路由和导航 4.2 状态管…...
《golang设计模式》第三部分·行为型模式-07-观察者模式(Observer)/发布者—订阅者模式
文章目录 1. 概念1.1 角色1.2 类图 2. 代码示例2.1 代码2.2 类图 1. 概念 观察者(Observer)指当目标对象状态发生变化后,对状态变化事件进行响应或处理的对象。 1.1 角色 Subject(抽象主题): 它可以有多…...
Maven中常用命令以及idea中使用maven指南
文章目录 Maven 常用命令compiletestcleanpackageinstallMaven 指令的生命周期maven 的概念模型 idea 开发maven 项目idea 的maven 配置idea 中创建一个maven 的web 工程在pom.xml 文件添加坐标坐标的来源方式依赖范围编写servlet maven 工程运行调试 Maven 常用命令 compile …...
深度学习之八(生成对抗网络--Generative Adversarial Networks,GANs)
概念 生成对抗网络(Generative Adversarial Networks, GANs)是一种深度学习模型,由 Ian Goodfellow 等人于2014年提出。GAN 的目标是通过训练两个神经网络(生成器和判别器),使得生成器能够生成与真实数据相似的样本,而判别器能够区分真实样本和生成样本。这两个网络相…...
内部网关协议_路由信息协议RIP_开放路径优先OSPF协议_基本知识
目录: 因特网路由选择协议概述 路由信息协议RIP 开放路径优先OSPF协议 因特网路由选择协议概述 一.路由选择分类 静态路由选择和动态路由选择 静态路由选择: 采用人工配置的方式给路由器添加网络路由、默认路由和特定主机路由等路由条目。静态路由选择简单、开销小&#…...
Linux python安装 虚拟环境 virtualenv
根目录创建 venvs 文件夹 sudo mkdir /venvs 进入 /venvs 目录 cd /venvsp 创建虚拟环境,前提要按照 python3 安装 的 命令 sudo apt install python3 sudo python3 -m venv 虚拟环境名 激活虚拟环境 sourcepippip /venvs/zen-venv/bin/activatepinpi 安装flask pip…...
洛谷 P1883 函数
P1883 函数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) Error Curves - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 这两题是一模一样的,过一题水两题。 分析 主要难点在于证明F(x)是一个单峰函数可以被三分,但是我随便画了几个f(x)之后发现好像…...
【C++心愿便利店】No.14---C++之探索list底层原理
文章目录 前言一、list的介绍及使用1.1 list的介绍1.2 list的使用1.2.1 list的构造1.2.2 list iterator的使用1.2.3 list capacity1.2.4 list element access1.2.5 list modifiers1.2.6 list operations1.2.7 list的迭代器失效 二、list的模拟实现2.1 定义一个结构体实现list的…...
【广州华锐互动】VR防溺水安全内容体验提高群众防溺水意识
在全球各地,溺水是导致儿童和青少年死亡的主要原因之一。据世界卫生组织的统计,全球每年有超过36万人因溺水而死亡,其中大部分是儿童和青少年。因此,提供有效的防溺水教育和培训至关重要。随着科技的发展,虚拟现实&…...
【Skynet 入门实战练习】游戏模块划分 | 基础功能模块 | timer 定时器模块 | logger 日志服务模块
文章目录 游戏模块基础功能模块定时器模块日志模块通用模块 游戏模块 游戏从逻辑方面可以分为下面几个模块: 注册和登录网络协议数据库玩法逻辑其他通用模块 除了逻辑划分,还有几个重要的工具类模块: Excel 配置导表工具GM 指令测试机器人…...
python内置模块binascii,二进制数据和ASCII字符串之间进行转换
一、简介 binascii是Python标准库中的一个模块,提供了在二进制数据和ASCII字符串之间进行转换的功能。它包含了一些用于处理二进制数据的函数,可以进行二进制数据的编码、解码和转换。 二、方法 binascii.unhexlify(hexstr):将十六进制表示…...
如何开启MySQL的慢查询日志
说明:如果需要查看某一条SQL查询速度慢,并对慢的SQL进行优化,那么开启MySQL慢查询日志是一定要做的事情,本文介绍如何开启MySQL的慢查询日志; 查看MySQL慢查询是否开启 首先,输入下面的命令,查…...
Spine的BoundingBoxAttachment碰撞检测
引擎版本 —— cocos creator 2.3.4 游戏代码: //优先初始化的时候,获取到cc.PhysicsPolygonColliderthis._poly this.dragonFooAni.node.getComponent(cc.PhysicsPolygonCollider);//下面的修改顶点位置的方法可以在update里面去执行//获取骨骼动画上…...
Turbo Intruder:Web安全测试的终极高性能攻击引擎实战指南
Turbo Intruder:Web安全测试的终极高性能攻击引擎实战指南 【免费下载链接】turbo-intruder Turbo Intruder is a Burp Suite extension for sending large numbers of HTTP requests and analyzing the results. 项目地址: https://gitcode.com/gh_mirrors/tu/tu…...
不止 for-in 和 Object.keys:用 TS 4.1+ 的模板字面量类型玩转 Enum 遍历与生成
超越运行时遍历:用 TS 4.1 模板字面量类型重构 Enum 元编程 当我们需要在 TypeScript 中处理枚举时,传统的 for-in 和 Object.keys 方法虽然实用,但它们在类型系统中留下的信息几乎为零。TypeScript 4.1 引入的模板字面量类型(Tem…...
中国县域金融机构网点统计1949-2021年
01、数据简介县域金融机构主要是指人民银行县支行、农村信用社及国有商业银行在县乡设立的分支机构无论从地理位置还是服务区域来说都与农民、农村、农业。数据名称:中国县域金融机构网点统计数据年份:1949-2021年02、相关数据指标本数据整理全国区县级金…...
OpCore Simplify终极指南:3小时智能搭建稳定黑苹果系统
OpCore Simplify终极指南:3小时智能搭建稳定黑苹果系统 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为复杂的OpenCore配置而烦恼吗…...
MaxKB4j:Java原生的企业级RAG与智能体引擎设计与实战
1. 项目概述:为什么我们需要一个Java原生的企业级智能问答引擎?如果你是一个Java技术栈的团队负责人或核心开发者,最近肯定被各种AI应用搞得眼花缭乱。ChatGPT、Claude、文心一言……这些大模型的能力让人惊叹,但当你真正想把它们…...
AMD Ryzen处理器终极调试指南:SMUDebugTool完全教程
AMD Ryzen处理器终极调试指南:SMUDebugTool完全教程 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: https://gitc…...
AI模型微调效率提升4.8倍,容器化推理延迟压至83ms——Docker AI Toolkit 2026企业级落地全栈实践,仅限首批认证用户解密
更多请点击: https://intelliparadigm.com 第一章:Docker AI Toolkit 2026企业级落地全景概览 Docker AI Toolkit 2026 是面向大规模AI工程化部署的轻量级容器化工具链,深度集成模型推理、数据管道编排、安全沙箱与可观测性能力,…...
IDM激活脚本终极指南:三步实现永久免费试用下载管理器
IDM激活脚本终极指南:三步实现永久免费试用下载管理器 【免费下载链接】IDM-Activation-Script IDM Activation & Trail Reset Script 项目地址: https://gitcode.com/gh_mirrors/id/IDM-Activation-Script 还在为Internet Download Manager(…...
如何利用AutoUnipus实现U校园自动化学习:3种模式深度解析与实战指南
如何利用AutoUnipus实现U校园自动化学习:3种模式深度解析与实战指南 【免费下载链接】AutoUnipus U校园脚本,支持全自动答题,百分百正确 2024最新版 项目地址: https://gitcode.com/gh_mirrors/au/AutoUnipus AutoUnipus是一款基于Python和Playwright的U校园…...
别再傻傻分不清了!ToB、ToC、ToG产品经理的日常工作到底差在哪?
ToB、ToC、ToG产品经理的日常:从需求挖掘到落地的全景对比 每天早上9点,当ToC产品经理正在分析用户点击热力图时,ToB产品经理可能正在与销售团队讨论某企业客户的定制需求,而ToG产品经理则可能在准备向某政府部门汇报项目进度的材…...
