栈(使用顺序表构建)

P. S.:以下代码均在VS2019环境下测试,不代表所有编译器均可通过。
P. S.:测试代码均未展示头文件stdio.h的声明,使用时请自行添加。

  

目录

  • 1、栈的概念
  • 2、栈的数组构建方法
    • 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 栈内数据的数量
  • 3、完整代码展示
  • 4、结语

1、栈的概念


  栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
   压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
   出栈:栈的删除操作叫做出栈。出数据也在栈顶。
  通俗一点的理解就是,栈就像是一个羽毛球筒一样,先放进去的羽毛球,最后才能拿出来,反而后放进去的可以先拿出来,也就是我们上面提到的LIFO:Last In First Out。

在这里插入图片描述


  而栈我们可以通过顺序表来构建,也可以通过链表来构建,本文讲述的是顺序表构建内容。

  下面进入正文。




2、栈的数组构建方法

2.1 前言


  构建栈的需求有三个文件,包括Stact.c(用来书写逻辑的内容)、Stact.h(用来书写逻辑的声明)、test.c(用来测试我们所书写的代码)。

2.2 正文


  我们先将我们的逻辑申明书写完成,这样后面的内容我们就可以按照逻辑声明的顺序一步一步完成。
  首先我们需要有一个顺序表如下,在书写的时候我们就直接将它重命名,以便我们后面代码的书写。
typedef struct Stact
{int* a;int top;int capacity;
}ST,*pST;//分别为结构体类型名,和结构体指针

  书写完会发现,我们结构体中的数组类型已经被定死了,如果我们以后想要往栈中存储不同类型的数据,需要一个一个在代码中查找 int 然后修改,十分麻烦,不如直接将类型重命名为一个新的名字,之后的代码中如果需要修改,则直接修改重命名的内容即可。

typedef int STDataType;
typedef struct Stact
{STDataType* a;int top;int capacity;
}ST,*pST;//分别为结构体类型名,和结构体指针

  在此之后,我们则需要在书写几个函数来执行我们的初始化,压栈,出栈,等操作。
  代码如下:

//初始化
void STInit(pST pst);
//顺序表的销毁
void STDestroy(pST pst);
//压栈
void STPush(pST pst, STDataType x);
//出栈
void STPop(pST pst);
//取栈顶数据
STDataType STTop(pST pst);
//栈判空
bool STEmpty(pST pst);
//栈的大小
int STSize(pST pst);

  下面我们对应其顺序一步一步书写

2.2.1 栈的初始化


  对于栈的初始化,代码如下:
void STInit(pST pst)
{assert(pst);pst->a = NULL;//让栈顶指向下一个位置pst->top = 0;//让栈顶指向当前位置//pst->top = -1;pst->capacity = 0;
}

  我们可以看到代码块中书写了两种方法,一种是让栈顶指向下一个位置,一种是让栈顶指向当前位置,两者皆可,本文采用的是令栈顶指向下一个位置的方法。


2.2.2 栈的销毁


  对于栈的销毁,代码如下:
void STDestroy(pST pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}

2.2.3 压栈


  对于数据的压栈,我们在开头就需要判断一下数组的空间是否足够,或者数组空间是否为NULL,如果不足或为NULL,我们需要对其进行空间开辟,使用 realloc 函数进行,其中我们知道本文采用的方法是将 top 指向下一个位置所处的下表,故代码如下:
void STPush(pST pst, STDataType x)
{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("STPush:realloc");return;}pst->a = tmp;}pst->a[pst->top] = x;pst->top++;
}

2.2.4 出栈


  对于出栈,就十分容易了,我们每一次压栈时使用的都是 top 来定位栈顶的位置,这里我们可以直接进行 top-- 操作,此时不用对栈顶的内容改变,下一次入栈时便会直接覆盖此时需要删除的内容。
  代码如下
void STPop(pST pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}

2.2.5 取栈顶数据


  取栈顶的数据代码如下:
STDataType STTop(pST pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}

2.2.6 对栈内数组判断是否为空


  判空代码如下:
bool STEmpty(pST pst)
{assert(pst);return pst->top == 0;
}

2.2.7 栈内数据的数量


  查看栈内数据的数量的代码如下:
int STSize(pST pst)
{assert(pst);return pst->top;
}




3、完整代码展示


  Stact.h:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>typedef int STDataType;typedef struct Stact
{STDataType* a;int top;int capacity;
}ST,*pST;//初始化
void STInit(pST pst);
//顺序表的销毁
void STDestroy(pST pst);
//压栈
void STPush(pST pst, STDataType x);
//出栈
void STPop(pST pst);
//取栈顶数据
STDataType STTop(pST pst);
//栈判空
bool STEmpty(pST pst);
//栈的大小
int STSize(pST pst);

  Stact.c:

#include "Stact.h"//初始化
void STInit(pST pst)
{assert(pst);pst->a = NULL;//让栈顶指向下一个位置pst->top = 0;//让栈顶指向当前位置//pst->top = -1;pst->capacity = 0;
}//顺序表的销毁
void STDestroy(pST pst)
{assert(pst);free(pst->a);pst->a = NULL;pst->top = pst->capacity = 0;
}//压栈
void STPush(pST pst, STDataType x)
{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("STPush:realloc");return;}pst->a = tmp;}pst->a[pst->top] = x;pst->top++;
}//出栈
void STPop(pST pst)
{assert(pst);assert(pst->top > 0);pst->top--;
}//取栈顶数据
STDataType STTop(pST pst)
{assert(pst);assert(pst->top > 0);return pst->a[pst->top - 1];
}//栈判空
bool STEmpty(pST pst)
{assert(pst);return pst->top == 0;
}//栈的大小
int STSize(pST pst)
{assert(pst);return pst->top;
}

  test.c:

#include "Stact.h"int main()
{// 入栈:1 2 3 4// 出栈:4 3 2 1  /  2 4 3 1ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);printf("%d ", STTop(&s));STPop(&s);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d ", STTop(&s));STPop(&s);}STDestroy(&s);
}




4、结语


  十分感谢您观看我的原创文章。
  本文主要用于个人学习和知识分享,学习路漫漫,如有错误,感谢指正。
  如需引用,注明地址。

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

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

相关文章

Jupyter notebook和 Jupyter lab内核死亡问题的原因和解决方案

写在前面&#xff1a;之前也遇到过几次内核死亡的问题&#xff0c;也一直没有想解决办法。这里总结一下并提出几个解决办法。 首先明确一下jupyter出现内核死亡的原因&#xff1a;jupyter lab 或者 jupyter notebook 本身是一个web服务&#xff0c; 无法支持高并发和频繁的计算…

栈与队列(包括例题一道)

栈 栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶&#xff0c;另一端称为栈底。 栈中的数据元素遵守后进先出 LIFO &#xff08; Last In First Out &#xff09;的原则。 压栈&…

libevent 梳理

C10K 背景 C10K问题&#xff1a;如何在一台物理机上同时服务 10000 个用户&#xff1f;这里 C 表示并发&#xff0c;10K 等于 10000&#xff1f; C10K 问题本质上是一个操作系统问题&#xff0c;需要考虑&#xff1a; 1.文件句柄数&#xff1a;每个客户连接都代表一个文件描述…

AI去衣技术在动画制作中的应用

随着科技的发展&#xff0c;人工智能&#xff08;AI&#xff09;已经在各个领域中发挥了重要作用&#xff0c;其中包括动画制作。在动画制作中&#xff0c;AI去衣技术是一个重要的工具&#xff0c;它可以帮助动画师们更加高效地完成工作。 AI去衣技术是一种基于人工智能的图像…

人际关系之【镜子、点到为止、脸色和蔼、懂自爱、弹性、试探】

人跟人是镜子 别人看到你的表情&#xff0c;当作一面镜子 儒家&#xff1a;先检查自己&#xff0c;容易进步 礼尚往来&#xff1a;一切往好处想&#xff0c;就会有好的结果 关于借钱&#xff1a; 没问题&#xff0c;我随时&#xff08;合适&#xff09;要用 个人和团体合在…

神经网络怎么把隐含层变量融合到损失函数中?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

【工具分享】Amnesia2勒索病毒解密工具

前言 Amnesia 勒索软件于 2017 年 4 月 26 日开始出现。Amnesia 主要通过 RDP&#xff08;远程桌面服务&#xff09;暴力攻击进行传播&#xff0c;允许恶意软件作者登录受害者的服务器并执行勒索行为。 特征 Amnesia 是一种用 Delphi 编程语言编写的勒索软件&#xff0c;它使…

Git撤回指定commit不保留更改

要撤销指定的commit但不保留这个commit中的更改&#xff0c;可以使用以下命令&#xff1a; git revert <commit_hash> --no-commit这里的<commit_hash>是你想要撤销的commit的哈希值。如果你想要在一个commit上使用这个命令&#xff0c;你可以用它的哈希值或者用H…

程序员的实用神器:助力软件开发的利器 ️

程序员的实用神器&#xff1a;助力软件开发的利器 &#x1f6e0;️ 程序员的实用神器&#xff1a;助力软件开发的利器 &#x1f6e0;️引言摘要自动化测试工具&#xff1a;保障代码质量的利剑 &#x1f5e1;️编写高效测试用例 持续集成/持续部署工具&#xff1a;加速交付的利器…

ASP.NET通用作业批改系统设计

摘  要 该系统采用B/S结构&#xff0c;以浏览器方式登陆系统&#xff0c;用ASP.NET作为开发语言&#xff0c;数据库则使用Microsoft SQL Server 2000实现。《通用作业批改系统》包括了学生子系统、教师子系统、管理员子系统三大模块&#xff0c;该系统主要完成学生&#xff…

基于C语言的贪吃蛇小游戏(简易版)

这篇博客会是对学习C语言成果的检测&#xff0c;为了实现贪吃蛇小游戏&#xff0c;我们用到的“工具”有&#xff1a;C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。 目录 1.简易版游戏效果 1.1欢迎界面 1.2游戏规则提示页面 1.3游戏进行页面 …

纯净水20、脉动30被指宰客!疯狂开始反噬小杨哥?

作为疯狂小杨哥早期粉&#xff0c;小柴好像很久没看到小杨哥的搞笑视频了。 自然&#xff0c;再在社交媒体上看到&#xff0c;小杨哥兄弟已经不再是那个青涩的少年了。 而是摇身一变不仅成为一个非常成功带货主播&#xff0c;且成为一个资本版图越来越多&#xff0c;玩的越来越…

现场面试题

这里写目录标题 1.sql1.1 只保留学生的最新成绩1.2 统计通话号码数1.3 更新地址 2.基础题2.1 请求序列第N位的值: 0, 1, 1, 2, ,3, 5, 8, 13, 21, 34.....第N位的值2.2 请写一段java代码&#xff0c;输出存在重复字母的单词 1.sql 1.1 只保留学生的最新成绩 表student中记录学…

CF988D题解

题目大意 题目传送门 题意&#xff1a;给你有 n n n 个数字的一个数列&#xff0c;问最多有多少个数字他们 两两的差是 2 的幂次方数。 思路 首先&#xff0c;我们想一个数能不能组成一个满足题目要求的序列&#xff0c;答案是肯定的。&#xff08;直接输出 a 1 a_1 a1​…

Android Studio之ImageView

ImageView是图像显示控件&#xff0c;与图形显示有关的属性说明如下: scaleType&#xff1a;指定图形的拉伸类型&#xff0c;默认是fitCenter。src&#xff1a;指定图形来源&#xff0c;src图形按照scaleType拉伸。 注意背景图不按scaleType指定的方式拉伸&#xff0c;背景默…

网络安全之交换基础

交换属于二层技术。路由器&#xff08;router&#xff09;是三层设备&#xff0c;可以基于IP地址转发&#xff0c;但需要路由表来记录。 交换机&#xff08;switch&#xff09;是二层设备&#xff0c;网桥&#xff08;switch&#xff09;也是二层设备&#xff0c;这两个都是基…

SegFix:预测边界和预测方向来修正边界

论文标题&#xff1a;SegFix: Model-Agnostic Boundary Refinement for Segmentation 论文地址&#xff1a;https://arxiv.org/pdf/2007.04269.pdf 代码地址&#xff1a;https://github.com/openseg-group/openseg.pytorch 两种loss监督 八种方向变回归问题为分类问题 代码地…

洛谷 P6136:【模板】普通平衡树(数据加强版) ← Splay树模板题

【题目来源】https://www.luogu.com.cn/problem/P6136【算法分析】 Splay 树简介及代码模板&#xff1a;https://blog.csdn.net/hnjzsyjyj/article/details/138504578【代码一&#xff1a;含 pushdown() 函数版本】 ● 本代码为洛谷 P6136 代码。题目来源为&#xff1a;https:…

PyQt6--Python桌面开发(1.安装配置环境)

一.PyQt6简介 PyQt&#xff1a;PyQt是一个功能强大且成熟的GUI框架&#xff0c;基于Qt库。它提供了丰富的组件、布局和主题选项&#xff0c;以及强大的功能和灵活性。PyQt的优点是它具有现代化的外观和丰富的功能&#xff0c;适用于复杂的GUI应用程序。然而&#xff0c;由于Py…