数据结构 栈(C语言实现)

news2024/11/25 16:44:25

绪论

        时间就是生命,时间就是速度,时间就是气力。——郭沫若;本章继续学习数据结构,本章主要讲了什么是栈以及栈的基本功能和实现方法。

 话不多说安全带系好,发车啦(建议电脑观看)


附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要


目录

1.栈的实现

1.1栈的结构​编辑

1.2栈的初始化

1.3栈的摧毁

1.4将数据插入栈中(入栈)

1.5将数据从栈中删除(出栈)

1.6查看栈顶元素

1.7查看栈中有几个元素

1.8判断栈是否是空的

2.实现栈的全部代码


知识点:

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶
可以把栈想成是一个水杯,水都是从一端进并从同一端出的(水也是后进的先出),放水进去时是压栈,把水倒出来是出栈。

细节:

栈的所要实现的框架有:栈可以由顺序表或者链表来作为底层实现,下面主要讲以顺序表来实现的过程

  1. 栈的结构
    1. 一个数组变量
    2. 记录元素个数的变量
    3. 一个记录容量的变量
  2. 栈所要实现的功能
    1. 初始化栈
    2. 摧毁栈
    3. 入栈
    4. 出栈
    5. 查看栈顶元素
    6. 查看栈中的元素个数
    7. 判断栈是否为空栈

1.栈的实现

1.1栈的结构

栈的结构:由数组变量、已经两个变量组成

typedef int datetype;//类型重命名,把int 重命名为 datetype 这样方便于改变结构中的存的类型
typedef struct stack//类型重命名
{
	datetype* date;//数组
	int size;//记录元素个数
	int capacity;//容量
}stack;//重命名为stack(避免每次都要写struct的繁琐)

1.2栈的初始化

主要是为了申请空间、以及初始化size、capacity。

void StackInit(stack* ps)
{
    //初始化两个变量
    ps->capacity = 3;//容量初始为3
    ps->size = 0;//元素的个数0

    ps->date = malloc(sizeof(datetype) * ps->capacity);//用malloc给数组开辟datetype类型的容量个大小的空间
    //此处就是开辟了 4(int) * 3(capacity) = 12 byte 大小的空间
    if (ps->date == NULL)//判断是否申请成功
    {
        perror("malloc");
        return;
    }
}

其中注意点是:把size定义成0这样方便于我们在顺序表中插入数据(插入数据的位置下标就是size),并且这样我们在拿出顶部数据时就需要-1后才能取到顶部数据了(有些程序员会定义成-1这样size就表示栈顶元素的下标,+1为栈中的元素个数)

1.3栈的摧毁

因为此处用的是顺序表来实现所以其摧毁方法就和顺序表一样

void StackDestroy(stack* ps)
{
    assert(ps);//判空
    ps->capacity = ps->size= 0;//置为0
    free(ps->date);//释放所借的空间
    ps->date = NULL;//将用完的指针置为NULL
}

1.4将数据插入栈中(入栈)

在date数组中插入数据,其中已经知道了size下标处就是数组中要插入数据的位置即date[ps->size]

void StackPush(stack* ps, datetype x)
{
    assert(ps);//判空
    if (ps->size== ps->capacity)//注意要检查空间是否足够
    {
        datetype* tmp = (datetype*)realloc(ps->date, sizeof(datetype) * ps->capacity * 2);//扩容扩大比原容量大两倍的空间大小
        if (tmp == NULL)//检查是否扩容成功
        {
            perror("realloc");
            return;
        }
        ps->date = tmp;//把tmp扩容好的空间,给到date
        ps->capacity *= 2;//注意别忘把capacity增加
    }
    ps->date[ps->size] = x;//在date的size下标位置处插入数据x
    ps->size++;//元素个数增加
}

1.5将数据从栈中删除(出栈)

对于出栈我们的方法和顺序表一样仅仅只是改变size元素个数

void StackPop(stack* ps)
{
    assert(ps);//为假就会报错
    assert(!StackEmpty(ps));//判断一下栈是不是空的
    ps->size--;//元素个数减一个
}

1.6查看栈顶元素

栈顶元素的下标是元素个数size-1故:

datetype StackTop(stack* ps)
{
    assert(ps);
    return ps->date[ps->size - 1];//返回栈顶元素
}

1.7查看栈中有几个元素

int StackSize(stack* ps)
{
    assert(ps);
    return ps->size;//返回size即可
}

1.8判断栈是否是空的

bool StackEmpty(stack* ps)
{
    assert(ps);
    return ps->size == 0;//等于0返回真,反之则为假
}

2.实现栈的全部代码

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

	typedef int datetype;

	typedef struct stack
	{
		datetype* date;
		int size;
		int capacity;
	}stack;



bool StackEmpty(stack* ps)
{
    assert(ps);
    return ps->size == 0;//等于0返回真,反之则为假
}



void StackInit(stack* ps)
{
    //初始化两个变量
    ps->capacity = 3;//容量初始为3
    ps->size = 0;//注意size指向的是下一个堆顶的位置

    ps->date = malloc(sizeof(datetype) * ps->capacity);//用malloc给数组开辟datetype类型的容量个大小的空间
    //此处就是开辟了 4(int) * 3(capacity) = 12 byte 大小的空间
    if (ps->date == NULL)//判断是否申请成功
    {
        perror("malloc");
        return;
    }
}

void StackDestroy(stack* ps)
{
    assert(ps);//判空
    ps->capacity = ps->size = 0;//置为0
    free(ps->date);//释放所借的空间
    ps->date = NULL;//将用完的指针置为NULL
}


void StackPush(stack* ps, datetype x)
{
    assert(ps);//判空
    if (ps->size == ps->capacity)//检查空间是否足够
    {
        datetype* tmp = (datetype*)realloc(ps->date, sizeof(datetype) * ps->capacity * 2);//扩容扩大比原容量大两倍的空间大小
        if (tmp == NULL)//检查是否扩容成功
        {
            perror("realloc");
            return;
        }
        ps->date = tmp;//把tmp扩容好的空间,给到date
        ps->capacity *= 2;//注意别忘把capacity增加
    }
    ps->date[ps->size] = x;//在date的top下标位置处插入数据x
    ps->size++;//元素个数增加
}

void StackPop(stack* ps)
{
    assert(ps);//为假就会报错
    assert(!StackEmpty(ps));//判断一下栈是不是空的
    ps->size--;//元素个数减一个
}

datetype StackTop(stack* ps)
{
    assert(ps);
    return ps->date[ps->size - 1];
}

int StackSize(stack* ps)
{
    assert(ps);
    return ps->size;
}

如果有任何问题欢迎讨论哈!

如果觉得这篇文章对你有所帮助的话点点赞吧!

持续更新大量数据结构细致内容,早关注不迷路。

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

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

相关文章

专业科普:什么是单片机?

一、什么是单片机 单片机诞生于20世纪70年代末&#xff0c;它是指一个集成在一块芯片上的完整计算机系统。单片机具有一个完整计算机所需要的大部分部件&#xff1a;CPU、内存、内部和外部总线系统&#xff0c;目前大部分还会具有外存。同时集成诸如通讯接口、定时器&#xff…

AI日报|GitHub报告:开发者正将AI视为新机会;突破ChatGPT的能力极限;AI会让我们变得愚蠢吗?

今日值得关注的人工智能新动态&#xff1a; AI 会让我们变得愚蠢吗&#xff1f;安永&#xff1a;与老板们不同&#xff0c;大多数工人正在拥抱 AI突破 ChatGPT 的能力极限谷歌推出AI虚拟试穿工具Gannett 涉足生成式 AIGitHub 报告&#xff1a;开发者将 AI 视为一个新机会专家敦…

Nik Color Efex 滤镜详解(4/5)

油墨效果 Ink 模拟特种相纸和调色剂的冲印效果。 颜色组合 Color Set 可选择不同的颜色组合。 强度 Strength 调整滤镜效果程度。 层次和曲线 Levels & Curves 用色阶和曲线来调整图像的影调和色调。常与其它滤镜组合使用。 通道 Channel 选择调节色调的通道。 通道除了…

C++基础(10)——函数模板和类模板

前言 本文主要介绍了C中函数模板和类模板基本知识 6.1&#xff1a;函数模板 模板函数的定义 template<typename T>函数的定义或声明 模板函数的两种使用方法&#xff08;编译器自动推测、显示指定T的类型&#xff09; 注意事项&#xff1a;模板一定要确定指出T的数据…

nuxt打包后文件过大的优化

在使用nuxt.js来做项目的时候&#xff0c;遇到了加载缓慢的问题。解决思路如下 1、大文件拆分 2、文件压缩 大文件拆分 通过nuxt build --analyze或者nuxt build -a命令来启用 在package.json中 添加–analyze&#xff0c;然后执行npm run build 打包后如下&#xff1a; …

MySQL数据库——事物

MySQL数据库——事物 一、事务的概念二、事务的ACID特点1.原子性2.一致性3.隔离性4.持久性5.事务隔离级别的作用范围 三、事务级别的查看与设置1.查询全局事务隔离级别2.查询会话事务隔离级别3.设置全局事务隔离级别4.设置会话事务隔离级别 四、事务控制语句1.测试提交事务2.测…

threeJs着色器

一、着色器 着色器&#xff08;Shaders &#xff09;是一种使用GLSL(OpenGL Shading Language)编写并在GPU上运行的程序。它们被用于定位几何体的每个顶点&#xff0c;并为该几何体的每个可见像素着色。使用“像素Pixel”来描述其实并不准确&#xff0c;因为渲染的每个点不一定…

神经网络小结:训练的全过程

这一节我们主要是将之前的知识穿起来&#xff0c;形成一个整体。如果之前的没看过可以回翻一下专栏。但是在整体回归之前&#xff0c;我们还需要学习一个小知识点——随机初始化 随机初始化 在神经网络中&#xff0c;我们大致的训练流程就是&#xff1a;通过前向传播得出当前…

指针和数组--指针和二维数组的关系

指针和二维数组的关系 目录 一、二维数组的行地址和列地址 二、通过二维数组的行指针和列指针来引用二维数组元素 一、二维数组的行地址和列地址 在C语言中&#xff0c;可将一个二维数组看成是由若干个一维数组构成的。例如若有下面的定义&#xff1a; int a[3][4]&#xf…

8、DuiLib创建子窗口

文章目录 1、创建子窗口2、创建子窗口 XML 配置文件 1、创建子窗口 一个大规模的应用不可能只有一个窗口&#xff0c;之前我们的案例都是在一个窗口实现的&#xff0c;接下来我们实现一个关于窗口&#xff0c;来介绍如何通过 DuiLib 实现子窗口管理。 2、创建子窗口 XML 配置…

小红书种草软文怎么写?教你几招

小红书种草软文写得好&#xff0c;能打消用户的疑虑&#xff0c;吸引更多的用户关注和购买你的产品&#xff0c;从而获得源源不断的流量和口碑&#xff0c;小红书种草软文怎么写&#xff1f;接下来伯乐网络传媒就来给大家讲解一下&#xff0c;教你几招超实用的方法&#xff01;…

MMSegmentation V0.27.0官方问题(包含多尺度设置)(四)

1、在单个 GPU 上再现性能 #179&#xff08;添加链接描述&#xff09; 2、如何使用 PyTorch 的 WeightedRandomSampler 或编写自定义采样器添加链接描述 4、使用独立的分段器 #2931添加链接描述 5、How to change the training policy from Iter to Epoch based on the existin…

【产品运营】如何通过数据分析掌握用户行为?

对于运营来说&#xff0c;需要掌握用户行为来制定不同的运营策略。而用户行为是通过数据分析得出的&#xff0c;那么&#xff0c;具体的数据分析是哪些数据&#xff0c;不同的数据又有什么区别&#xff1f; 通过本文能够学到什么&#xff1f; 快速了解一款APP。行业趋势&#…

完美解决 ---latex运行正常,但是公式显示有问题,latex公式不显示等号 = 和加号 +

文章目录 一、问题展示二、分析原因三、 我的解决办法四、 \usepackage{txfonts}宏包是什么&#xff1f;五、\usepackage{amsmath}宏包是什么&#xff1f;总结 一、问题展示 latex运行正常&#xff0c;但是公式显示有问题&#xff0c;latex公式不显示等号 和加号 二、分析原…

C++基础(9)——文件操作

前言 本文主要介绍了C中文件操作基本知识 5.1&#xff1a;C语言使用标准C库函数读写文件复习 fgets、fputs&#xff08;读写文本文件&#xff09; int main(int argc, char *argv[]) {FILE *file;file fopen("a.txt", "a");if (file NULL){perror(&q…

flutter项目启动安卓模拟器不好使的问题

这里写自定义目录标题 一. 新建的flutter项目安卓模拟器不能使用二当上面操作完成以后,新建的flutter项目可以使用安卓模拟器,但是老项目不好使的解决方法 在flutter项目中,ios模拟器好使,安卓模拟器不好使. 分为2种情况: 一. 新建的flutter项目安卓模拟器不能使用 但是在and…

专业的性能测试工具都具备哪些特点?

在软件开发和系统运行过程中&#xff0c;性能是一个关键的指标&#xff0c;直接影响到用户体验和系统的可靠性。为了确保软件和系统的性能达到预期水平&#xff0c;专业的性能测试工具成为必不可少的一环。那专业的性能测试工具都具备哪些特点&#xff1f;探讨其在软件开发和系…

分享几个免费设计生成及参考工具(第三期)

今天来给大家分享几个国外免费的设计生成工具 Uxcrush https://www.uxcrush.com/ 一个收集优秀 Figma 资源的网站&#xff0c;包括网站模板、移动模板、UI套件、图标、设备模型、插画等等。希望为 Figma 用户提供一个方便找到最适合他们设计项目或学习目标的资源站。 unpromp…

用Python写了一个下载网站所有内容的软件,可见即可下

目录标题 前言效果展示环境介绍:代码实战获取数据获取视频采集弹幕采集评论 GUI部分尾语 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 今天我们分享一个用Python写下载视频弹幕评论的代码。 顺便把这些写成GUI&#xff0c;把这些功能放到一起让朋友用起来更方便~ 效果…

FAQ页面在SaaS产品中的应用

随着云计算和软件即服务&#xff08;SaaS&#xff09;的快速发展&#xff0c;越来越多的企业选择将业务迁移到云端&#xff0c;以更好地管理和运营他们的业务。在这种背景下&#xff0c;SaaS产品的出现成为了企业管理和运营的新趋势。SaaS产品通过云端的方式&#xff0c;为企业…