链栈的基本操作(c语言实现)

栈的概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

栈的结构

定义栈

栈有两种常见的定义方式:基于数组(或动态数组)的实现和基于链表的实现。

1. 基于数组(或动态数组)的栈定义

基于数组的实现是最常见的栈定义方式。这种实现方式使用一个固定大小或动态调整大小的数组来存储栈中的元素。数组的一个端点被视作栈底(通常不直接操作),而另一端点被视作栈顶,用于执行压栈和弹栈操作。

  • 压栈(push):将新元素添加到数组的栈顶位置,并更新栈顶指针。
  • 弹栈(pop):移除数组的栈顶元素,并更新栈顶指针。
  • 查看栈顶元素(peek):返回数组的栈顶元素但不移除它。
  • 判断栈是否为空(isEmpty):检查栈顶指针是否指向栈底位置。

基于数组的实现简单且效率高,但存在一个问题:当栈满时,需要预先分配更大的数组空间,这可能导致空间浪费。为了解决这个问题,可以使用动态数组,它在需要时自动扩展大小。

2. 基于链表的栈定义

基于链表的实现使用链表数据结构来存储栈中的元素。链表的头部(或尾部)被视作栈顶,用于执行压栈和弹栈操作。

  • 压栈(push):创建一个新节点,将新元素存储在该节点中,然后将该节点添加到链表的头部(或尾部)。
  • 弹栈(pop):移除链表的头部(或尾部)节点,并返回该节点中存储的元素。
  • 查看栈顶元素(peek):返回链表的头部(或尾部)节点中存储的元素但不移除该节点。
  • 判断栈是否为空(isEmpty):检查链表是否为空。

基于链表的实现不需要预先分配固定大小的空间,因此更加灵活。然而,由于链表中每个节点都需要额外的存储空间来存储指针,因此这种实现方式在内存使用上可能不如基于数组的实现高效。

在实际应用中,根据具体需求和场景选择合适的栈定义方式是很重要的。例如,在需要频繁扩容且内存空间充足的情况下,基于动态数组的栈可能是一个好选择;而在内存使用受限或需要高度灵活性的情况下,基于链表的栈可能更合适。

链栈的定义

typedef int STDataType;//栈中存储的元素类型(这里用整型举例)typedef struct Stack
{STDataType* a;//栈int top;//栈顶int capacity;//容量,方便增容
}Stack;

这里定义了一个结构体,并给它起了一个别名Stack。结构体中包含三个成员:

  • a:这是一个指向STDataType类型的指针,用于存储栈中的元素。它实际上是一个数组,用来存放栈中的各个元素。
  • top:这是一个整数,表示栈顶的位置。在栈中,通常使用top来追踪栈顶元素的位置。当栈为空时,top的值可能是-1或其他表示空栈的值;当栈不为空时,top的值是栈顶元素的索引。
  • capacity:这也是一个整数,表示栈的容量。这通常用于动态数组实现的栈,以便在栈满时知道何时需要扩容。

 栈的基本操作

// 支持动态增长的栈
typedef int STDataType;
typedef struct Stack
{STDataType* _a;int _top; // 栈顶int _capacity; // 容量
}Stack;
// 初始化栈
void StackInit(Stack* ps); 
// 入栈
void StackPush(Stack* ps, STDataType data); 
// 出栈
void StackPop(Stack* ps); 
// 获取栈顶元素
STDataType StackTop(Stack* ps); 
// 获取栈中有效元素个数
int StackSize(Stack* ps); 
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
int StackEmpty(Stack* ps); 
// 销毁栈
void StackDestroy(Stack* ps);

初始化栈

//初始化栈
void StackInit(Stack* pst)
{assert(pst);pst->a = (STDataType*)malloc(sizeof(STDataType)* 4);//初始化栈可存储4个元素pst->top = 0;//初始时栈中无元素,栈顶为0pst->capacity = 4;//容量为4
}

通过这个函数,我们实现了对栈的初始化

销毁栈

因为栈的内存空间是动态开辟出来的,当我们使用完后必须释放其内存空间,避免内存泄漏。

//销毁栈
void StackDestroy(Stack* pst)
{assert(pst);free(pst->a);//释放栈pst->a = NULL;//及时置空pst->top = 0;//栈顶置0pst->capacity = 0;//容量置0
}

入栈

压栈:栈的插入操作叫做进栈 / 压栈 / 入栈。(入数据在栈顶)

进行入栈操作前,我们需要检测栈的当前状态,若已满,则需要先对其进行增容,然后才能进行入栈操作。

//入栈
void StackPush(Stack* pst, STDataType x)
{assert(pst);if (pst->top == pst->capacity)//栈已满,需扩容{STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType)*pst->capacity *2);if (tmp == NULL){printf("realloc fail\n");exit(-1);}pst->a = tmp;pst->capacity *= 2;//栈容量扩大为原来的两倍}pst->a[pst->top] = x;//栈顶位置存放元素xpst->top++;//栈顶上移
}

出栈

出栈:栈的删除操作叫做出栈。(出数据也在栈顶)

出栈操作比较简单,即让栈顶的位置向下移动一位即可。但需检测栈是否为空,若为空,则不能进行出栈操作。

//出栈
void StackPop(Stack* pst)
{assert(pst);assert(!StackEmpty(pst));//检测栈是否为空pst->top--;//栈顶下移
}

获取栈顶元素

获取栈顶元素,即获取栈的最上方的元素。若栈为空,则不能获取。

//获取栈顶元素
STDataType StackTop(Stack* pst)
{assert(pst);assert(!StackEmpty(pst));//检测栈是否为空return pst->a[pst->top - 1];//返回栈顶元素
}

检测栈是否为空

检测栈是否为空,即判断栈顶的位置是否是0即可。若栈顶是0,则栈为空。

//检测栈是否为空
bool StackEmpty(Stack* pst)
{assert(pst);return pst->top == 0;
}

获取栈中有效元素个数

因为top记录的是栈顶,使用top的值便代表栈中有效元素的个数。

//获取栈中有效元素个数
int StackSize(Stack* pst)
{assert(pst);return pst->top;//top的值便是栈中有效元素的个数
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3323.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【JAVA】503.下一个更大元素II | 42. 接雨水 | 84.柱状图中最大的矩形

class Solution {public int[] nextGreaterElements(int[] nums) {int len nums.length;int[] res new int[len];Deque<Integer> stack new LinkedList<>();Arrays.fill(res,-1);for(int i 0 ;i<len*2; i){//循环数用取模的方式int j i % len;while(!stack…

JVM虚拟机监控及性能调优实战

目录 jvisualvm介绍 1. jvisualvm是JDK自带的可以远程监控内存&#xff0c;跟踪垃圾回收&#xff0c;执行时内存&#xff0c;CPU/线程分析&#xff0c;生成堆快照等的工具。 2. jvisualvm是从JDK1.6开始被继承到JDK中的。jvisualvm使用 jvisualvm监控远程服务器 开启远程监控…

C#参数修饰符params

C#参数修饰符params params 关键字允许在 C# 中指定一个方法参数&#xff0c;该参数接受可变数量的参数。这意味着你可以传递一个由指定类型的参数组成的逗号分隔的列表&#xff0c;编译器会将它们打包成一个数组。 示例 : using System;class Program {static void Main(st…

智能家居—ESP32开发环境搭建

相关文章 毕业设计——基于ESP32的智能家居系统(语音识别、APP控制) 智能家居—ESP32开发环境搭建 一、下载安装二、验证三、资料获取 一、下载安装 下载安装 vscode 安装插件 创建工程 二、验证 写一个简单的函数来验证一下功能 void setup() {// put your setup c…

SpringMVC笔记——SpringMVC基础Tomcat环境配置

Tomcat安装配置 下载Apache Tomcat 进入官网https://tomcat.apache.org/&#xff0c;选择tomcat 9 这边使用idea开发&#xff0c;建议直接下载压缩包 无法访问下载的可以直接用我的下载链接&#xff1a;https://cloudreve.zxbdwy.online/s/6nSA 提取码&#xff1a;w1pwk3将压…

婚姻情感 20

婚姻情感 20 怎么和异性聊天&#xff1f;1. 第一步&#xff1a;判断关系2. 第二步&#xff1a;适应状态3. 第三步&#xff1a;信号识别4. 第四步&#xff1a;反应判断5. 第五步&#xff1a;深层控制6. 第六步&#xff1a;复盘定局7. 第七步&#xff1a;破局操控场景描述 怎么和…

【Java并发知识总结 | 第七篇】Java并发相关概念总结(程序/进程/线程、并行/并发、同步/异步、死锁/避免、线程安全/三大特性)

文章目录 7.并发相关概念总结&#xff08;程序/进程/线程、并行/并发、同步/异步、死锁/避免、线程安全/三大特性&#xff09;7.1程序、进程与线程7.2并行和并发7.3同步和异步7.4什么是死锁&#xff1f;如何避免&#xff1f;7.5何为线程安全&#xff1f;以及三大特性 7.并发相关…

java多线程-并发和并行

进程 并发 进程中的线程是由CPU进行调度的&#xff0c;但是CPU能够处理的进程数量有限为了保证所有的线程都在运行&#xff0c;CPU会快速切换&#xff0c;给外界的感觉就是所有的线程都在运行&#xff0c;这就是并发。 并行

【毕设绝技】基于 SpringCloud 的在线交易平台商城的设计与实现(一)

毕业设计是每个大学生的困扰&#xff0c;让毕设绝技带你走出低谷迎来希望&#xff01; 基于 SpringCloud 的在线交易平台商城的设计与实现 一、摘 要 随着互联网的快速发展&#xff0c;人们对商品经济的消费和思考不再停留在传统的经济模式上&#xff0c;网上购物商城是企业与…

安卓手机APP开发__媒体开发部分__常见问题答疑解惑

安卓手机APP开发__媒体开发部分__常见问题答疑解惑 目录 1.修复"Cleartext HTTP traffic not permitted"错误 2.修复"SSLHandshakeException", "CertPathValidatorException" 和 "ERR_CERT_AUTHORITY_INVALID" 错误 3.为什么一些媒…

vue3第二十三节(全局属性方法应用)

vue2 与 vue3 的全局属性使用方法区别 1、globalProperties getcurrentinstace vue3 中已经移除对外暴露 getcurrentinstace,建议使用下面两种 2、provide | inject 3、mitt 事件总线程 1、vue2 通过 prototype 实例上挂载属性/方法,用于全局调用 // main.js import Vue from…

C语言入门课程学习记录4

C语言入门课程学习记录4 第18课 - signed 与 unsigned第19课 - 再论数据类型第20课 - 经典问题剖析第21课 - 程序中的辅助语句&#xff08;上&#xff09;第22课 - 程序中的辅助语句&#xff08;下&#xff09; 本文学习自狄泰软件学院 唐佐林老师的 C语言入门课程&#xff0c;…

git submudles 代码如果提交到一个ID 上

要将git submudles代码提交到一个ID上&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. 确保已将本地仓库更新到远程仓库最新版本&#xff0c;避免提交出现冲突。 2. 进入子模块目录&#xff0c;进行添加、修改等操作&#xff0c;并使用git add暂存更改。 3. 使用git c…

pytest教程-30-测试数据管理插件-pytest-datadir

领取资料&#xff0c;咨询答疑&#xff0c;请➕wei: June__Go 上一小节我们学习了pytest重复执行用例插件pytest-repeat&#xff0c;本小节我们讲解一下测试数据管理插件-pytest-datadir。 在软件测试中&#xff0c;有效管理测试数据对于编写全面的测试用例至关重要。Pytest…

vue基础教程(7)——构建项目级首页

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、页面结构二、侧边栏三、主体部分总结 前言 前面我们学习了vue的路由和登录页搭建&#xff0c;本文将和大家共同学习首页的搭建。 首页示例如图&#xff1a; 很多项目经验比较少的同学&#xff0c;一般都是对某些语…

深入探索Android Service:后台服务的终极指南(下)

引言 Service组件在Android应用中扮演着至关重要的角色&#xff0c;尤其是在执行后台任务和进程间通信时。然而&#xff0c;Service的不当使用可能会导致性能问题&#xff0c;甚至影响系统稳定性。本文将深入探讨Service性能优化技巧的最佳实践。 一、Service性能优化策略 Ser…

浅谈操作系统中的重要概念——进程

文章目录 一、什么是程序&#xff1f;二、什么是进程&#xff1f;三、进程与程序有什么区别&#xff1f;四、OS是如何管理进程的4.1、使用 结构体 进行描述进程4.2 、使用数据结构组织众多进程4.3、PCB4.3.1、PCB 里有哪些属性4.3.1.1 pid4.3.1.2 内存指针4.3.1.3 文件描述符表…

2024年如何保存微信小程序里的音频文件#下载高手

今年是2024年&#xff0c;仍然有很多人不知道如何下载&#xff0c;本文就带你们学会如何下载微信小程序里面的音频素材 这里要用到一个工具&#xff0c;下载高手 下载高手链接&#xff1a;https://pan.baidu.com/s/1JUWmNXozWSS3xgmvpdyf0g?pwd1234 提取码&#xff1a;1234…

后端程序员利用 AI 给网站制作专业 favicon

看看你的 Chrome 浏览器顶部的标签页&#xff0c;每个标签页前面有一个小小的图标&#xff0c;这个就是 favicon&#xff0c;如果你将网页保存到收藏夹&#xff0c;前面也会是这个小图标。这个图标有时候就是网站的 Logo&#xff0c;有时候也不太一样。 上面截图中&#xff0c…

【C语言】typedef

为一个数据类型起一个新的别名 typedef int INTEGER; INTEGER a,b; a1; b2;typedef char ARRAY20[20]; ARRAY20 a1,a2,s1,s2;typedef struct stu{char name[20];int age;char sex; }STU; STU body1,body2;typedef int (*PTR_TO_ARR)[4]; PTR_TO_ARR p1,p2;typedef int (*PTR_TO…