当前位置: 首页 > news >正文

数据结构:栈的实现(C实现)

在这里插入图片描述

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》

文章目录

  • 前言
  • 一、栈的实现思路
    • 1. 结构的定义
    • 2. 初始化栈(StackInit)
    • 3. 入栈(StackPush)
    • 4. 出栈(StackPop)
    • 5. 获取栈顶元素(StackTop)
    • 6. 检查栈是否为空(StackEmpty)
    • 7. 销毁栈(StackDestroy)
  • 二、代码实现
  • 总结


前言

栈:一种特殊的线性结构,其只允许在一端进行插入,删除数据。允许操作数据的一端被称为栈顶,另一端被称为栈底
本篇博客将要实现的是数组栈


一、栈的实现思路

对于栈的特殊性,用数组(在数组尾部插入删除数据) 和 链表(头插头删数据)实现栈的时间复杂度都是O(1),难度不大。
数组栈的优劣

  • 数组支持随机访问(用下标访问数据),许多算法需要随机访问的支持,如二分法…
  • 缓存利用率高

  • 空间不够时要扩容
  • 有时会造成空间浪费

1. 结构的定义

栈的结构非常简单
一个指向动态开辟空间的指针,一个记录实际空间大小的变量,一个记录栈顶元素的下标即可。

在这里插入图片描述

typedef int STDataType;typedef struct Stack
{STDataType* data;int top;//栈顶下标int capacity;//空间大小
}Stack;

2. 初始化栈(StackInit)

data指针指向动态开辟的空间,capacity记录此时空间大小,top置为0。

  • top 置0,表示栈顶数据将要插入的位置。
  • top 置-1,表示此时栈顶数据的位置。

这里,采用top 置0。

在这里插入图片描述

//初始化栈#define SIZE 4void StackInit(Stack* ps)
{assert(ps);ps->data = (STDataType*)malloc(sizeof(STDataType) * SIZE);if (ps->data == NULL){perror("malloc");exit(-1);}ps->top = 0;ps->capacity = SIZE;
}

3. 入栈(StackPush)

因为top初始化为0,所以直接在top下标处入数据即可。但要注意,在入数据前要检查容量,如果top == capacity 要扩容。

  • 此处检查容量的操作,可以封装成一个函数,但没必要,因为栈的操作只有入栈要检查容量,其它的操作并不需要检查容量,封装成一个函数反而效率减低了(函数的调用要形成函数栈帧)。

在这里插入图片描述

//入栈
void StackPush(Stack* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){STDataType* tmp = (STDataType*)realloc(ps->data, sizeof(STDataType) * (ps->capacity * 2));if (tmp == NULL){perror("realloc");exit(-1);}ps->data = tmp;ps->capacity *= 2;}ps->data[ps->top] = x;ps->top++;
}

4. 出栈(StackPop)

top 表示的是栈顶数据将要入栈的位置,那么出栈操作,只需要让top 减 1即可。(下次入栈数据会直接覆盖)
但要注意,top = 0 时,表示栈内没有数据,不能进行出栈操作。

  • 出栈操作不能获取数据

在这里插入图片描述

//出栈
void StackPop(Stack* ps)
{assert(ps);assert(ps->top != 0);ps->top--;
}

5. 获取栈顶元素(StackTop)

top 指向的是数据将要入栈的位置,也就是栈顶数据的下一个位置。
那么要获取栈顶数据,只需要读取top - 1处即可。但要注意,如果top = 0,那么top - 1 = -1,会越界访问,所以top = 0 时,不能获取栈顶元素。

在这里插入图片描述


//获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->data[ps->top - 1];
}

6. 检查栈是否为空(StackEmpty)

top 指向的是数据将要入栈的位置,其数值也表示栈内数据个数。
所以我们只需要进行 top == 0 的判断,即可知道栈是否为空。

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

7. 销毁栈(StackDestroy)

free掉动态开辟的空间,使capacity 置 0,top 置 0。

//销毁栈
void StackDestroy(Stack* ps)
{assert(ps);free(ps->data);ps->top = 0;ps->capacity = 0;
}

二、代码实现

Stack.h 文件存放的是函数的声明,头文件的引用,结构体的定义
Stack.c 文件存放的是函数的实现

//Stack.h  文件#pragma once#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>#define SIZE 4typedef int STDataType;typedef struct Stack
{STDataType* data;int top;int capacity;
}Stack;//初始化栈
void StackInit(Stack* ps);//入栈
void StackPush(Stack* ps, STDataType x);//出栈
void StackPop(Stack* ps);//获取栈顶元素
STDataType StackTop(Stack* ps);//检查栈是否为空
bool StackEmpty(Stack* ps);//销毁栈
void StackDestroy(Stack* ps);

//Stack.c  文件#include "Stack.h"//初始化栈
void StackInit(Stack* ps)
{assert(ps);ps->data = (STDataType*)malloc(sizeof(STDataType) * SIZE);if (ps->data == NULL){perror("malloc");exit(-1);}ps->top = 0;ps->capacity = SIZE;
}//入栈
void StackPush(Stack* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity){STDataType* tmp = (STDataType*)realloc(ps->data, sizeof(STDataType) * (ps->capacity * 2));if (tmp == NULL){perror("realloc");exit(-1);}ps->data = tmp;ps->capacity *= 2;}ps->data[ps->top] = x;ps->top++;
}//出栈
void StackPop(Stack* ps)
{assert(ps);assert(ps->top != 0);ps->top--;
}//获取栈顶元素
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->data[ps->top - 1];
}//检查栈是否为空
bool StackEmpty(Stack* ps)
{assert(ps);return ps->top == 0;
}//销毁栈
void StackDestroy(Stack* ps)
{assert(ps);free(ps->data);ps->top = 0;ps->capacity = 0;
}

总结

以上就是我对于栈的实现。
在这里插入图片描述

相关文章:

数据结构:栈的实现(C实现)

个人主页 &#xff1a; 个人主页 个人专栏 &#xff1a; 《数据结构》 《C语言》 文章目录 前言一、栈的实现思路1. 结构的定义2. 初始化栈(StackInit)3. 入栈(StackPush)4. 出栈(StackPop)5. 获取栈顶元素(StackTop)6. 检查栈是否为空(StackEmpty)7. 销毁栈(StackDestroy) 二、…...

v-md-editor自定义锚点(生成目录)数组转树结构

接前两篇博文&#xff0c;最终方案终于定了&#xff0c;也把之前做的编辑器模式给否决了&#xff0c;原因是系统中有老的文档需要平替&#xff0c;因此就不能通过编辑器这种模式了&#xff0c;太麻烦了。 最终方案&#xff1a;线下手动pandoc word转markdown&#xff0c;然后将…...

java 11 新特效解读(2)

目录 全新的HTTP 客户端API 更简化的编译运行程序 废弃Nashorn引擎 ZGC 优势&#xff1a; ZGC的设计目标是&#xff1a; 在当前JDK中看不到什么&#xff1f; 一个标准化和轻量级的JSON API 新的货币API 展望 全新的HTTP 客户端API HTTP&#xff0c;用于传输网页的…...

linux patch 和 git patch

一、Linux patch 文件生成和应用 生成方式1&#xff1a;patch #多文件打 patch diff -uparN file1 file2 > xx.diff diff -uparN folder1 folder12 > xx.diff ------------------------------------------------------- diff --help -u 显示有差异行的前后几行(上下文)…...

【vue Dplayer】播放hls视频流

准备工作 安装Dplayer和hls.js npm install dplayer --save npm install hls.js --save准备测试流 hls测试地址&#xff1a;&#xff08;截止2023.08.08有效&#xff09; http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8 <template><d…...

给不蒜子(busuanzi)统计数据增加初始值

背景 最近把个人博客迁移到了Hexo框架&#xff0c;并使用了Butterfly主题&#xff0c;得益于博客框架的易用性和主题功能的丰富程度&#xff0c;感觉非常的香。我对比了很多Hexo主题&#xff0c;这一个算是在功能、审美、文档等各方面几乎完美符合我需求的。 Butterfly很贴心…...

WebStorm

WebStorm 介绍下载安装Activation 介绍 WebStorm是由JetBrains公司开发的一款集成开发环境&#xff08;IDE&#xff09;&#xff0c;主要专注于前端开发和Web开发。它旨在提供一套强大的工具和功能&#xff0c;以支持开发者在前端项目中编写、调试和维护代码。 JetBrains官网: …...

代码随想录算法训练营day59

文章目录 Day59 下一个更大元素II题目思路代码 接雨水题目思路代码 Day59 下一个更大元素II 503. 下一个更大元素 II - 力扣&#xff08;LeetCode&#xff09; 题目 给定一个循环数组&#xff08;最后一个元素的下一个元素是数组的第一个元素&#xff09;&#xff0c;输出每…...

大模型训练时间估算

文章目录 开激活重计算不开激活重计算开激活重计算 GPU利用率一般在 0.3 - 0.55 之间,假定为0.45 4090 理论性能:FP16:82.58 TFLOPS 不开激活重计算 我们来说一下系数8或6是怎么来的: 对于每个模型参数,都进行2次浮点数计算,即计算Y = AB 时,先将元素按位相乘,再按位相…...

函数的模拟实现

题一&#xff1a; 模拟实现strncpy #include <stdio.h>void my_strncpy(char* arr2, char* arr1, size_t num){int i 0;for (i 0; i < num; i){*(arr2 i) *(arr1 i);}}int main(){char arr1[] "hello liangzai";char arr2[10] { 0 };//strncpy(ar…...

CSDN博客批量查询质量分https://yma16.inscode.cc/请求超时问题(设置postman超时时间)(接口提供者设置了nginx超时时间)

文章目录 查询链接问题请求超时原因解决谷歌浏览器超时问题办法&#xff08;失败了&#xff09;谷歌浏览器不支持设置请求超时时间&#xff08;谷歌浏览器到底有没限制请求超时&#xff1f;貌似没有限制&#xff1f;&#xff09;看能否脱离浏览器请求&#xff0c;我们查看关键代…...

什么是 CSRF 攻击?

概念 CSRF 攻击指的是跨站请求伪造攻击&#xff0c;攻击者诱导用户进入一个第三方网站&#xff0c;然后该网站向被攻击网站发送跨站请求。如果用户在被攻击网站中保存了登录状态&#xff0c;那么攻击者就可以利用这个登录状态&#xff0c;绕过后台的用户验证&#xff0c;冒充用…...

[内网渗透]CFS三层靶机渗透

文章目录 [内网渗透]CFS三层靶机渗透网络拓扑图靶机搭建Target10x01.nmap主机探活0x02.端口扫描0x03.ThinkPHP5 RCE漏洞拿shell0x04.上传msf后门(reverse_tcp)反向连接拿主机权限 内网渗透Target2&#xff08;1&#xff09;路由信息探测&#xff08;2&#xff09;msf代理配置&a…...

一百五十一、Kettle——Linux上安装的kettle8.2开启carte服务以及配置子服务器

一、目的 kettle8.2在Linux上安装好可以启动界面、并且可以连接MySQL、Hive、ClickHouse等数据库后&#xff0c;准备在Linux上启动kettle的carte服务 二、实施步骤 &#xff08;一&#xff09;carte服务文件路径 kettle的Linux运行的carte服务文件是carte.sh &#xff08;二…...

2023高教社杯数学建模A题 B题C题 D题 E题思路代码分析

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 全国大学生数学建模…...

从ChatGLM2-6B来看大模型扩展上下文和加速推理相关技术

ChatGLM2-6B 是开源中英双语对话模型 ChatGLM-6B 的第二代版本&#xff0c;在保留了初代模型对话流畅、部署门槛较低等众多优秀特性的基础之上&#xff0c;ChatGLM2-6B 引入了如下新特性&#xff1a; 更强大的性能&#xff1a;基于 ChatGLM 初代模型的开发经验&#xff0c;全面…...

Unity特效总览

一、粒子 Unity中的粒子组件叫做Particle System。 粒子系统顾名思义&#xff0c;与“微粒”有关。粒子系统会生成和发射很多粒子&#xff0c;通过控制粒子的生成数量、大小、角度、速度、贴图和颜色等众多属性&#xff0c;可以实现或真实或炫酷的各种效果。其中&#xff0c;…...

Unity中人物控制器

在Unity中控制器是很常见的功能&#xff0c;一般的人物控制器有两种方法&#xff0c;一种是通过代码实现&#xff0c;另外一种就是通过Unity中的API实现。   这里主要介绍第一种方法。 首先对控制器步骤进行分析。 步骤1&#xff1a;通过方向键控制人物移动。 步骤2&#xff…...

零钱兑换-输出组合数

1.暴力递归 &#xff08;1&#xff09;剩余金额小于0&#xff0c;无解 剩余金额等于0&#xff0c;有解 剩余金额大于0&#xff0c;继续递归 &#xff08;2&#xff09;从大的硬币到小的硬币&#xff0c;可以减少循环次数 #include <bits/stdc.h> using namespace std;…...

Mybatis 小结

一、Mybatis 基本构成 MyBatis的整体分为基础支持层、核心处理层、接口。 1.1、基础支持层 1.1.1、数据源模块 MyBatis自身提供了相应的数据源实现&#xff0c;也提供了与第三方接口数据源集成的接口&#xff0c;这些功能都位于数据源模块之中。 1.1.2、事务管理模块 …...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

在软件开发中正确使用MySQL日期时间类型的深度解析

在日常软件开发场景中&#xff0c;时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志&#xff0c;到供应链系统的物流节点时间戳&#xff0c;时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库&#xff0c;其日期时间类型的…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...