手撕数据结构 —— 栈(C语言讲解)

目录

1.认识栈

什么是栈

栈的示意图

2.如何实现栈

3.栈的实现

Stack.h中接口总览

具体实现

结构的定义

初始化栈

销毁栈

入栈

出栈

取栈顶元素

获取有效元素的个数

判断栈是否为空

4.完整代码附录

Stack.h

Stack.c


1.认识栈

什么是栈

栈是一种特殊的线性表,只允许在固定的一端进行数据的插入和删除操作;

  • 进行数据的插入和删除的一端叫做栈顶,另一端叫做栈底。
  • 栈中的数据必须严格遵守后进先出的原则,这也是栈这种数据结构最重要的特点。

栈的示意图

两个专业术语:

  • 入栈:栈的插入数据元素的操作叫做入栈。

  • 出栈:栈的删除数据元素的操作叫做出栈。

入栈和出栈都是在栈顶进行的。

2.如何实现栈

要想实现栈,必须满足以下两个条件:

  • a、控制在一端进行数据的插入和删除
  • b、满足后进先出的原则。

基于上述条件,我们可以使用数组或者链表来实现栈,那么使用哪种数据结构来实现栈更好呢?

我们可以对比一下:

数组(顺序表)链表(单链表)
头插效率O(N)O(1)
头删效率O(N)O(1)
尾插效率O(1)O(N)
尾删效率O(1)O(N)

可以看出,使用数组(顺序表)来实现栈的话,需要将尾部作为栈顶,插入数据和删除数据的时间复杂度都是O(1)。使用链表(单链表)来实现栈的话,需要将头部作为栈顶,插入数据和删除数据的时间复杂度都是O(1)。

但是相对而言,使用数组实现栈更优,因为数组没有太多的指针操作,删除数据的时候只需要让size-- 即可(size是数组中有效元素的个数),插入数据的时候直接赋值即可。

我们实现栈的时候,采用数组的形式实现数组栈。

3.栈的实现

实现栈的时候,我们主要实现Stack.h 和 Stack.c这两个文件,Stack.h用来存放声明,Stack.c用来存放定义。

Stack.h中接口总览

具体实现

结构的定义

因为静态的栈不实用,我们实现的数组栈采用动态增长的形式。

  • a指向动态开辟的内存空间的起始地址。
  • top指向栈顶元素的下一个位置。
  • capacity表示栈的容量,当容量不够的时候,需要动态扩容。

初始化栈

初始化栈的之后,将a置为空,capacity和top都为0。

  • top初始化为0表示top指向栈顶元素的下一个位置。
  • top如果初始化为-1表示top指向栈顶元素。
  • 两种方式实现都可以,我们采用第一种,这样的好处是top的值直接就可以表示栈中数据元素的个数。

注意:指向物理空间的指针ps不能为空,后面涉及该指针变量的地方都一样。

销毁栈

销毁栈的时候,只需要将动态申请的空间释放,并将指向这块空间的指针置空;然后将top和capacity都置为0即可。

入栈

实现入栈需要注意以下几个点:

  • 栈空间不能为空,使用断言assert()暴力判断。
  • 注意空间是否足够,空间不够时需要扩容。
  • 元素入栈之后,top记得++。

出栈

出栈时需要注意以下几点:

  • 指向物理空间的指针不能为空。
  • 栈中元素个数 >0 时元素才能出栈。
  • 元素出栈之后记得将top-- 。 

取栈顶元素

我们定义结构的时候,将top定义为栈顶元素的下一个位置,top-1就表示栈顶元素的下标,直接返回栈顶元素即可。

获取有效元素的个数

top也能表示栈中有效元素的个数,直接返回top即可。

判断栈是否为空

top表示栈中有效数据的个数,当top == 0时,栈为空;当top != 0时,栈不为空。

4.完整代码附录

Stack.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int STDataType;
typedef struct Stack
{STDataType* a;    // 指向动态开辟的顺序表 int top;          // 指向栈顶元素的下一个位置 int capacity;     // 表示栈的容量 
}ST;void STInit(ST* ps);                 // 初始化栈 
void STDestroy(ST* ps);              // 销毁栈 
void STPush(ST* ps, STDataType x);   // 入栈 
void STPop(ST* ps);                  // 出栈 
STDataType STTop(ST* ps);            // 取栈顶元素 
int STSize(ST* ps);                  // 获取有效元素的个数 
bool STEmpty(ST* ps);                // 判断栈是否为空 

Stack.c

#include "Stack.h"void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->capacity = 0;ps->top = 0;
}void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}void STPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity)     // 当 top==capacity时就需要扩容了  {// 初始空间为4,扩容按照两倍扩 int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;// 当a为空的时候,realloc的功能类似于malloc STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);if (tmp == NULL)             // 判断扩容是否成功 {perror("realloc fail");exit(-1);}ps->a = tmp;                 // 将开辟的空间赋值给变量a ps->capacity = newCapacity;  // 更新容量 }ps->a[ps->top] = x;              // 元素入栈 ps->top++;                       // top++指向栈顶元素的下一个位置 
}void STPop(ST* ps)
{assert(ps);          // 指针不能为空 assert(ps->top > 0); // 栈中元素个数 >0 元素才能出栈 --ps->top;           // 元素出栈之后记得将top-- 
}STDataType STTop(ST* ps)
{assert(ps);            assert(ps->top > 0);        // 栈中有元素 return ps->a[ps->top - 1];  // 返回栈顶元素 
}int STSize(ST* ps)
{assert(ps);return ps->top;
}bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}

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

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

相关文章

学视频剪辑需要电脑吗 学视频剪辑需要什么条件

态度决定成败&#xff0c;学剪辑亦是如此。我们都在学习剪辑的道路上寻找答案&#xff0c;电脑就像指引答案的工具&#xff0c;但它本身并不是答案。所以&#xff0c;好电脑不等于好剪辑师。想要学好视频剪辑&#xff0c;你只需要一个态度端正的自己。有关学视频剪辑需要电脑吗…

Spring Cloud Stream 3.x+kafka 3.8整合

Spring Cloud Stream 3.xkafka 3.8整合&#xff0c;文末有完整项目链接 前言一、如何看官方文档(有深入了解需求的人)二、kafka的安装tar包安装docker安装 三、代码中集成创建一个测试topic&#xff1a;testproducer代码producer配置&#xff08;配置的格式&#xff0c;上篇文章…

基于SpringBoot+Vue的疫苗预约接种管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

DELL R720服务器阵列数据恢复,磁盘状态为Foreign

服务器无法正常进入系统&#xff0c;物理磁盘状态变成了Foreign 虚拟磁盘状态变成了Failed 阵列已经丢失了&#xff0c;需要手工强制导入外部配置 单击 Main Menu 屏幕上的 Configuration Management。单击 Manage Foreign Configuration 单击 Preview Foreign Configurati…

60. 排列序列【回溯】

文章目录 60. 排列序列解题思路Go代码 60. 排列序列 60. 排列序列 给出集合 [1,2,3,...,n]&#xff0c;其所有元素共有 n! 种排列。 按大小顺序列出所有排列情况&#xff0c;并一一标记&#xff0c;当 n 3 时, 所有排列如下&#xff1a; “123”“132”“213”“231”“31…

VMDK 0X80BB0005 VirtualBOX虚拟机错误处理-数据恢复——未来之窗数据恢复

打开虚拟盘文件in7.vmdk 失败. Could not get the storage format of the medium 7\win7.vmdk (VERR_NOT_SUPPORTED). 返回 代码:VBOX_E_IPRT_ERROR (0X80BB0005) 组件:MediumWrap 界面:IMedium {a a3f2dfb1} 被召者:IVirtualBox {768 cd607} 被召者 RC:VBOX_E_OBJECT_NOT_F…

Qt基础对话框QDialog

模态显示对话框 调用exec方法可以使得对话框模态显示&#xff0c;但是一个阻塞函数 [virtual slot] int QDialog::exec() 对话框的三个槽函数 accept [virtual slot] void QDialog::accept(); reject [virtual slot] void QDialog::reject() done [virtual slot] void QDia…

Nginx从入门到实战(八):版本平滑无感知,不停机升级

一、查看旧版本信息 可以通过nginx -V命令&#xff0c;来查看当前nginx的版本信息&#xff0c;和配置参数。 [rootnb001 sbin]# nginx -V -bash: nginx: command not found [rootnb001 sbin]# ./nginx -V nginx version: nginx/1.20.1 built by gcc 4.8.5 20150623 (Red Hat …

Spring Boot读取resources目录下文件(打成jar可用),并放入Guava缓存

1、文件所在位置&#xff1a; 2、需要Guava依赖&#xff1a; <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>23.0</version></dependency>3、启动时就读取放入缓存的代码&#xf…

gaussdb hccdp理论考试总结

判断题1分&#xff0c;单选题2分&#xff0c;多选题3分 共50道题&#xff0c;满分100分&#xff0c;60分通过。 理论考试知识点占比&#xff1a; 理论考试参考策略&#xff1a; 1.7张PPT看一遍 2.思考题做一遍 3.模拟题做一遍 4.7张PPT再看一遍 5.考题知识点过一遍 6.考试前一…

ZYNQ使用XGPIO驱动外设模块(前半部分)

目录 目录 一、新建BD文档&#xff0c;添加ZYNQ处理器 1.BD文档: 2.在Vivado中&#xff0c;BD文件的生成过程通常包括以下步骤&#xff1a; 1)什么是Tcl Console: 3.PL部分是FPGA可编程逻辑部分&#xff0c;它提供了丰富的IO资源&#xff0c;可以用于实现各种硬件接口和功…

QT 连接SQL SEVER 之后无法读取浮点和整型

1、ODBC Driver 的版本要对应上。 if (!strDbDirPath.isEmpty())m_strDbDirPath strDbDirPath;m_strDatabaseName strDatabaseName;if (m_database.isOpen() || m_bConnected){qDebug() << QString("QODBC:已经连接成功&#xff01;") << "\n&quo…

Power Pivot, PowerView和PowerBI在产品宣传,功能,及本质上有什么不同?

微软的Power Pivot、Power View和Power BI是三个不同的数据分析和商业智能工具&#xff0c;它们在产品宣传、功能和本质上有所区别&#xff0c;并且各自适用于不同的场景。 1. Power Pivot Power Pivot是一种数据建模技术&#xff0c;用于在Excel中创建数据模型&#xff0c;建…

Halcon 3D应用 - 胶路提取

1. 需求 本文基于某手环&#xff08;拆机打磨处理&#xff09;做的验证性工作&#xff0c;为了项目保密性&#xff0c;只截取部分数据进行测试。 这里使用的是海康3D线激光轮廓相机直线电机的方式进行的高度数据采集&#xff0c;我们拿到的是高度图亮度图数据。 提取手环上的胶…

Java面向对象编程--高级

目录 一、static关键字 1.1 静态变量 1.2 静态内存解析 1.3 static的应用与练习 二、单例设计模式 2.1 单例模式 2.2 如何实现单例模式 三、代码块 3.1 详解 3.2 练习&#xff0c;测试 四、final关键字 五、抽象类与抽象方法 5.1 abstract 5.2 练习 六、接口 6.…

d3dcompiler_47.dll缺失怎么修复,马上教你六种靠谱的方法

在使用计算机的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中一个就是某些dll文件缺失。比如d3dcompiler_47.dll&#xff0c;这个文件是DirectX的一部分&#xff0c;主要用于编译DirectX的着色器代码。当这个文件缺失时&#xff0c;一些程序就无法正常运行了&…

typescript使用webpack打包编译问题

解决方案&#xff1a;在webpack.config.js中的mdule.exports中设置mode。 再次运行npm run start即可。

pytest的基础入门

pytest判断用例的成功或者失败 pytest识别用例失败时会报AssertionError或者xxxError错误&#xff0c;当捕获异常时pytest无法识别到失败的用例 pytest的fixture夹具 pytest的参数化 #coding:utf-8 import pytestfrom PythonProject.pytest_test.funcs.guess_point import ge…

GAN(Generative Adversarial Nets)

GAN(Generative Adversarial Nets) 引言 GAN由Ian J. Goodfellow等人提出&#xff0c;是Ian J. Goodfellow的代表作之一&#xff0c;他还出版了大家耳熟能详的花书&#xff08;Deep Learning深度学习&#xff09;&#xff0c;GAN主要的思想是同时训练两个模型&#xff0c;生成…

【重磅升级】基于大数据的股票量化分析与预测系统

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长 QQ 名片 :) 1. 项目简介 伴随全球经济一体化和我国经济的快速发展&#xff0c;中国股票市场对世界经济的影响力不断攀升&#xff0c;中国股市已成为全球第二大股票交易市场。在当今的金融市场中&#xff0c;股票价格的波动…