【初阶数据结构篇】栈的实现(赋源码)

文章目录

    • 1 代码位置
    • 2 概念与结构
      • 1.1概念
      • 1.2结构
    • 2 栈的实现
      • 2.1 栈的初始化和销毁
        • 2.1.1 初始化
        • 2.1.2 销毁
      • 2.2 栈顶插入和删除数据
        • 2.2.1 栈顶插入数据(压栈)
        • 2.2.2 栈顶删除数据(出栈)
      • 2.3 返回栈顶数据
      • 2.4 返回栈的有效数据个数
      • 2.5 打印栈中数据

1 代码位置

[gitee](Stack/Stack · petrichor/2024-summer-c-language - 码云 - 开源中国 (gitee.com))

2 概念与结构

1.1概念

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

压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,入数据在栈顶

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

在这里插入图片描述

1.2结构

栈的实现⼀般可以使⽤数组或者链表实现,相对⽽⾔数组的结构实现更优⼀些。因为数组在尾上插⼊数据的代价⽐较⼩。

数组尾插时间复杂度:O(1) 链表尾插时间复杂度:O(N)


2 栈的实现

因为栈的底层是数组,所以栈的实现方法和动态顺序表大致相同,且因为栈只能在栈顶出和入数据,所以栈还要更简单一些

Stack.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include<stdbool.h>
typedef int STDataType;
typedef struct Stack
{STDataType* arr;STDataType capacity;STDataType top;
}ST;//初始化和销毁
void STInit(ST*);
void STDestroy(ST*);//栈顶---入数据,出数据
void StackPush(ST*, STDataType);
void StackPop(ST*);//判空
bool StackEmpty(ST*);//取栈顶元素
STDataType StackTop(ST*);//获取栈中有效元素个数
int STSize(ST*);

test.c

  • 用来测试我们写的函数(函数的调用)
  • 这一部分就是自己写的时候用的测试用例,随便什么都行

最好是写一个方法测试一次,不然找错误的时候会很痛苦😜

#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
void STTest01()
{ST st;STInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 5);//StackPop(&st);//StackPop(&st);//StackPop(&st);//StackPop(&st);//StackPop(&st);// printf("size: %d\n", STSize(&st));while (!StackEmpty(&st)){STDataType data = StackTop(&st);printf("%d ", data);StackPop(&st);}printf("\n");printf("size: %d\n", STSize(&st));}
int main()
{STTest01();return 0;
}

Stack.c

函数方法的实现,重点重点!!!

在每一个方法的第一排都使用assert宏来判断ps是否为空(避免使用时传入空指针,后续解引用都会报错)

2.1 栈的初始化和销毁

2.1.1 初始化
void STInit(ST* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}
2.1.2 销毁
void STDestroy(ST*ps)
{assert(ps);if (ps->arr)free(ps->arr);ps->arr = NULL;ps->top = ps->capacity = 0;
}

注:栈的特性决定了它无法被遍历和随机访问和插入数据,只能在栈顶操作!!!所以打印方法不能和顺序表一样遍历,具体方法会在后面讲到


2.2 栈顶插入和删除数据

2.2.1 栈顶插入数据(压栈)

插入数据的时候一定要判断空间是否足够,不足要增容,一般2倍或3倍增容!!!

养成好习惯,不要用arr直接接收动态开辟空间的地址,否则开辟失败arr变为NULL,连原来的内存块都找不到了,这就造成了内存泄漏!!!

void StackPush(ST* ps, STDataType x)
{assert(ps);//空间是否足够if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = 2 * newcapacity;}ps->arr[ps->top++] = x;
}
2.2.2 栈顶删除数据(出栈)

删除数据的时候一定要判断栈是否为空,即top不能为0!!!

bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));--ps->top;
}
  • 只要让top–即可,不影响后来的插入(数据会被覆盖)

2.3 返回栈顶数据

STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top-1];
}

2.4 返回栈的有效数据个数

int STSize(ST* ps)
{return ps->top;
}

2.5 打印栈中数据

  • 之前说到栈不能通过遍历来打印,所以只有通过循环取栈顶元素后再让其出栈的方式来依次打印,打印完了栈也为空了!
while (!StackEmpty(&st)){STDataType data = StackTop(&st);printf("%d ", data);StackPop(&st);}printf("\n");

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "Stack.h"
void STInit(ST* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;
}void STDestroy(ST*ps)
{assert(ps);if (ps->arr)free(ps->arr);ps->arr = NULL;ps->top = ps->capacity = 0;
}void StackPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc fail!");exit(1);}ps->arr = tmp;ps->capacity = 2 * newcapacity;}ps->arr[ps->top++] = x;
}bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));--ps->top;
}STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top-1];
}int STSize(ST* ps)
{return ps->top;
}

对于栈这一种结构的实现,因为和顺序表差别不大,更细节的内容就没有过多赘述,对以数组作为底层结构的线性表的实现方法有什么疑问的话,推荐先去看这一篇哦->顺序表的实现方法

以上就是栈的实现方法啦,各位大佬有什么问题欢迎在评论区指正,您的支持是我创作的最大动力!❤️
请添加图片描述

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

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

相关文章

C++类型强转

C(四)类型强转 新类型的强制转换可以提供更好的控制强制转换过程&#xff0c;允许控制各种不同种类的强 制转换。C提供了四种转化 static_cast&#xff0c;reinterpret_cast&#xff0c;dynamic_cast 和 const_cast 以满足不同需求&#xff0c;C风格的强制转换好处是&#xff…

【深度学习】语音合成,TTS,PaddleSpeech

https://paperswithcode.com/task/text-to-speech-synthesis https://github.com/PaddlePaddle/PaddleSpeech https://github.com/coqui-ai/TTS https://github.com/keonlee9420/Expressive-FastSpeech2 https://github.com/TensorSpeech/TensorflowTTS docker镜像&#x…

【笔记】人工智能大模型在电力系统运行控制中的应用综述及展望

据统计,截至 2019 年底,我国风电和光伏的装机容量已经达到 415 GW,美国的可再生能源全年发电量已超过燃煤发电,同时欧洲计划在 2050 年完成 100% 可再生能源互联电网的建设。为了响应国家提出的“碳达峰”“碳中和”政策,国家电网公司提出在有效保障能源安全供应的前提下,…

嵌入式人工智能(31-基于树莓派4B的气压传感器-BMP280)

1、气压传感器 气压传感器&#xff08;Pressure Sensor&#xff09;是一种用于测量气体压力的装置。它可以将气体压力转换为电信号输出&#xff0c;进而实现对气体压力的监测和控制。气压传感器广泛应用于工业自动化、气象观测、建筑监测、航空航天等领域。 气压传感器的工作…

未来的智能农业:智能合约如何提升农业生产效率和可持续性

随着全球人口的增长和资源的有限性&#xff0c;农业生产面临着越来越大的挑战。如何在提高生产效率的同时保障可持续发展成为全球农业发展的关键问题。智能合约作为一种基于区块链技术的自动化执行合约&#xff0c;正在逐渐应用于农业领域&#xff0c;为农业生产带来了新的机遇…

Redis:RDB持久化

1. 简介 实现类似照片记录效果的方式&#xff0c;就是把某一时刻的数据和状态以文件的形式写到磁盘上&#xff0c;也就是 快照。这样一来即使故障宕机&#xff0c;快照文件也不会丢失&#xff0c;数据的可靠性也就得到了保证。 这个快照文件就称为RDB文件(dump.rdb)&#xff0c…

从代码层面熟悉UniAD,开始学习了解端到端整体架构

0. 简介 最近端到端已经是越来越火了&#xff0c;以UniAD为代表的很多工作不断地在不断刷新端到端的指标&#xff0c;比如最近SparseDrive又重新刷新了所有任务的指标。在端到端火热起来之前&#xff0c;成熟的模块化自动驾驶系统被分解为不同的独立任务&#xff0c;例如感知、…

数据倾斜优化思路实践

数据倾斜&#xff0c;顾名思义&#xff0c;就是在计算过程中数据分散度不够&#xff0c;导致某个节点数据过于集中&#xff0c;从而导致任务执行效率大大降低。参照对比下MR的整体流程和ODPS&#xff0c;整体结合理解数据倾斜发生的几个生命周期的节点&#xff0c;如下图&#…

WordPress设置固定连接后提示404

WordPress设置固定链接后出现404错误通常是因为服务器的伪静态规则没有正确设置。以下是几种常见的服务器环境下的解决方案&#xff1a; 宝塔面板&#xff1a;如果服务器安装了宝塔面板&#xff0c;可以在宝塔面板中选择对应的WordPress伪静态规则并保存设置 。 Apache服务器&a…

Linux——DNS服务搭建

&#xff08;一&#xff09;搭建nginx 1.首先布置基本环境 要求能够ping通外网&#xff0c;有yum源 2.安装nginx yum -y install nginx 然后查看验证 3.修改网页配置文件 修改文件&#xff0c;任意编写内容&#xff0c;然后去物理机测试 &#xff08;二&#xff09;创建一…

C++知识点总结:2.类和对象(自用)

类和对象 1. 类和对象的关系2. 对象指针3. 在堆上创建对象4. 成员访问限定符5. 名字编码&#xff08;Name Mangling&#xff09;6.构造函数7.构造函数的重载8.初始化列表8. 成员变量初始化的顺序&#xff08;通过初始化列表&#xff09;9. 初始化 const 成员变量10. 析构函数11…

【机器学习】pytorch 常用函数解析

目录 一、基本函数介绍 1.1 nn.Module 类 1.2 nn.Embedding 1.3 nn.LSTM 1.4 nn.Linear 1.5 nn.CrossEntropyLoss 1.6 torch.save 1.7 torch.load 1.8 nn.functional 1.9 nn.functional.softmax 本文主要对 pytorch 中用到的函数进行介绍&#xff0c;本文会不断更新~…

C语言内存函数精讲

目录 引言 1.内存分配函数malloc 2.内存释放函数free 3.内存拷贝函数memcpy 4.内存移动函数memmove 5.内存设置函数memset 6.内存比较函数memcmp 总结 引言 在C语言编程中&#xff0c;内存管理是核心技能之一。C语言提供了一系列内存操作函数&#xff0c;这些函数在动…

把Hexo博客迁移到新电脑

原文&#xff1a;https://blog.c12th.cn/archives/31.html 前言 把博客迁移到新电脑&#xff0c;以前推 Github 仓库不用配Key也能推&#xff0c;现在需要配Key了… 准备工作 确保在新电脑上配置好 Node.js 的环境 安装hexo npm install hexo-cli -g安装插件 npm install …

nmcli修改连接名 笔记240725

nmcli修改连接名 nmcli connection modify 原名 con-name 新名nmcli connection modify UUID con-name 新名通过网络名或uuid删除连接 nmcli connection delete 连接名或uuid通过设备名删除连接 nmcli device disconnect 设备连接用 nmcli device connect 设备名 创建的连接…

在android中怎么处理后端返回列表中包含图片id,如何将列表中的图片id转化成url

在 Android 中实现从包含图片 ID 的列表获取实际图片 URL 并显示图片,你可以使用以下步骤: 定义数据模型:创建一个 Java 或 Kotlin 类来表示列表中的对象。 网络请求:使用 Retrofit 或其他网络库来获取图片 URL。 异步处理:使用 AsyncTask、RxJava 或 Kotlin 协程来处理网…

算法训练 2024.7.27 17:25

目录 1. 两数之和2.反转链表3. 是否为有效的括号4.最长公共前缀5.合并两个有序数组6. 岛屿的个数7. 最小路径和8. 三数之和9. 计数质数10. 字符串转换整数 ( atoi) 1. 两数之和 题目&#xff1a; 给定一个整数数组 nums 和一个目标值 target&#xff0c;请你在该数组中找出和为…

Python 在自动化中的实际应用:用 Python 简化繁琐任务

文章目录 1、概述2、自动化文件和目录管理3.数据处理与分析4.网页爬虫5. 系统管理6。定时任务7.结语 1、概述 这篇文章将深入探讨Python在自动化中的实际应用&#xff0c;帮助您用Python简化繁琐任务。 我们将从多个方面入手&#xff0c;展示如何利用Python进行文件管理、数据…

百度贴吧爬虫实战(BeautifulSoup+lxml)

文章目录 BeautifulSouplxml使用场景具体代码具体解析1. 导入模块2. 定义爬虫类3. 初始化方法4. 获取URL列表5. 获取页面内容6. 提取页面数据7. 保存数据8. 运行爬虫9. 主程序 总结 在实际爬虫之前还需要了解和下载两个模块&#xff1a;BeautifulSoup和lxml。 BeautifulSoup 和…

jmeter-beanshell学习-try处理异常

有时候代码执行过程中&#xff0c;出现一些不能处理的情况&#xff0c;就会报错&#xff0c;还影响之后的代码执行&#xff0c;就需要跳过异常。 上面这情况报错了&#xff0c;还影响了下面的打印。beanshell用try和catch处理异常&#xff0c;下面是try的用法&#xff0c;和if有…