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

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


前言:

还是举一个生活中的例子,大家都玩过积木,当我们把积木叠起来的时候,如果要拿到最底部的积木,我们必须从顶端一个一个打出,最后才能拿到底部的积木,也就是后进先出(先进后出)的道理,今天分享栈的实现的本质也就是后进先出(先进后出)。

目录

前言:

栈的概念及结构

栈的实现

栈的结构定义

初始化栈

压栈(数据的添加)

出栈(数据的删除)

获取栈顶元素

获取栈中有效元素个数

判断栈是否为空

栈实现的总代码(vs2022)

头文件Stack.h

函数文件Stack.c

测试Text.c


栈的概念及结构

要去实现栈,我们要知道什么是 栈,栈的结构是什么,该从什么方向去实现。

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除
操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出 LIFO Last In First Out)
的原则。
压栈:栈的插入操作叫做进栈/ 压栈 / 入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。

 

如图我们会发现数据进栈出栈后的顺序倒置了,其实栈不只是可以将顺序导致,我们也可以先把A,B放进去,拿出来之后,再将C,D放进去,全部拿出来可以得到C,D,A,B,所以栈最后导致的结果是多种多样的,这取决你如何运用栈了。

栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上
插入数据的代价比较小。
我们在这里使用数组进行实现,如图所示我们把数组的尾部作为栈顶,这样可以轻松的进行压栈操作(增加数据),如果使用链表的话,我们找到尾节点需要进行遍历找尾(利用循环去找为节点),这样就增多了时间的消耗,这里使用数组来实现栈,可以提高算法效率。

栈的结构定义

typedef int STDataType;typedef struct Stack
{ STDataType* a;int top;     //栈顶int capacity;//栈容量
}Stack;

栈只需要对栈顶进行操作,所以我们有一个变量top表示栈顶。后面需要判断栈是否为空,我们需要一个变量capacity表示栈容量。

初始化栈

void StackInit(Stack* ps)
{assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);ps->top = 0;ps->capacity = 4;
}

这里我们创造了4个整型变量的空间,所以capacity给4。

压栈(数据的添加)

void StackPush(Stack* ps,STDataType x)
{assert(ps);if (ps->top == ps->capacity)//考虑到空间大小不够,使用realloc进行增容操作{STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));if (tmp == NULL)//要注意tmp可能为空的情况。{printf("realloc fail!!!");exit(-1);}ps->a = tmp;//别忘了把指针a指向新开辟的空间ps->capacity *= 2;}ps->a[ps->top] = x;ps->top++;//注意个数的增加
}

在压栈的时候要注意几点:

1.压栈时要考虑空间的大小是否足够,不够时要进行增容操作。

2.增容操作后的原指针要指向新指针,保证数据不会丢失。

3.压栈过后要对将top往后移动一位,因为top的指向是数组最后元素的下一个位置。

出栈(数据的删除)

void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);//top不能小于或等于0,因为top是指向栈顶元素的下一个位置ps->top--;
}

因为是用数组进行栈的实现,我们只需要把栈顶往前移动一位,就表示删除了数据。

获取栈顶元素

STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];//因为top是指向栈顶元素的下一个位置,所以要-1}

一定注意对ps->top>0进行断言,保证栈的元素不为空。

获取栈中有效元素个数

int StackSize(Stack* ps)
{assert(ps);return ps->top;}

top指向的数组尾部元素后一位,刚好是数组中有效元素的个数。

判断栈是否为空

bool StackEmpty(Stack* ps)//bool也可以使用 表示真假
{assert(ps);return ps->top == 0;
}

检查栈是否为空,如果不为空则返回0,如果为空则返回非零结果。

栈实现的总代码(vs2022)

头文件Stack.h

#pragma once#include<stdio.h>
#include<stdbool.h>
#include<stdlib.h>
#include<assert.h>
typedef int STDataType;typedef struct Stack
{ STDataType* a;int top;     //栈顶int capacity;//栈容量
}Stack;
//初始化栈
void StackInit(Stack* ps);
//栈的销毁
void StackDestory(Stack* ps);
//压栈
void StackPush(Stack* ps,STDataType x);
//出栈
void StackPop(Stack* ps);
//获取栈顶元素
STDataType StackTop(Stack* ps);
//获取栈中有效元素的个数
int StackSize(Stack* ps);
//检查栈是否为空,如果不为空则返回0,如果为空则返回非零结果
bool StackEmpty(Stack* ps);//bool也可以使用 表示真假

函数文件Stack.c

#include"Stack.h"void StackInit(Stack* ps)
{assert(ps);ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);ps->top = 0;ps->capacity = 4;
}
void StackDestory(Stack* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;}
//入栈
void StackPush(Stack* ps,STDataType x)
{assert(ps);if (ps->top == ps->capacity)//考虑到空间大小不够,使用realloc进行增容操作{STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));if (tmp == NULL)//要注意tmp可能为空的情况。{printf("realloc fail!!!");exit(-1);}ps->a = tmp;//别忘了把指针a指向新开辟的空间ps->capacity *= 2;}ps->a[ps->top] = x;ps->top++;//注意个数的增加
}
void StackPop(Stack* ps)
{assert(ps);assert(ps->top > 0);//top不能小于或等于0,因为top是指向栈顶元素的下一个位置ps->top--;
}
STDataType StackTop(Stack* ps)
{assert(ps);assert(ps->top > 0);return ps->a[ps->top - 1];//因为top是指向栈顶元素的下一个位置,所以要-1}
int StackSize(Stack* ps)
{assert(ps);return ps->top;}
bool StackEmpty(Stack* ps)//bool也可以使用 表示真假
{assert(ps);return ps->top == 0;
}

测试Text.c

#include"Stack.h"void StackText()
{Stack st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 5);while (!StackEmpty(&st)){printf("%d ", StackTop(&st));StackPop(&st);}StackDestory(&st);
}int main()
{StackText();return 0;
}

好啦,这就是今天学习的分享啦!看到希望大家的三连呀!

如果有不当之处,欢迎大佬指正!


相关文章:

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

前言&#xff1a; 还是举一个生活中的例子&#xff0c;大家都玩过积木&#xff0c;当我们把积木叠起来的时候&#xff0c;如果要拿到最底部的积木&#xff0c;我们必须从顶端一个一个打出&#xff0c;最后才能拿到底部的积木&#xff0c;也就是后进先出&#xff08;先进后出&a…...

前端三大主流框架对比

在现代前端开发中&#xff0c;React、Vue和Angular是三大流行的框架/库。它们各自有独特的优缺点&#xff0c;适用于不同的开发需求和项目规模。下面是对这三者的详细比较&#xff1a; 一、 React 简介&#xff1a; 由Facebook开发和维护&#xff0c;是一个用于构建用户界面…...

AOP~面向切面编程介绍

AOP基础 概述 AOP&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程、面向方面编程&#xff09;&#xff0c;面向特定方法的编程。 动态代理是面向切面编程最主流的实现。 SpringAOP是Spring框架的高级技术&#xff0c;旨在管理bean对象的过程中&#xff0c…...

Android SurfaceFlinger——GraphicBuffer的提交(三十三)

在 SurfaceFlinger 中,我们 dequeueBuffer 和 queueBuffer 是 Surface 控制接口中非常重要的两个函数,分别用于从 Surface 的 BufferQueue 中取出缓冲区和向 BufferQueue 提交(队列)缓冲区。这两个函数在生产者和消费者模型中扮演着核心角色,确保了图像数据的高效和有序传…...

创维汽车滁州永通体验中心开业仪式暨超充车型区域上市会圆满成功

2024年7月20日&#xff0c;创维汽车滁州永通体验中心盛大开业&#xff0c;当日&#xff0c;创维汽车市场部经理周世鹏、安徽大区总监王大明等领导参加本次开业盛典&#xff0c;共同见证创维汽车滁州永通体验中心成功落地。 2021年&#xff0c;新能源乘用车高速发展&#xff0c;…...

【PHP】系统的登录和注册

一、为什么要学习系统的登录和注册 系统的登录和注册可能存在多种漏洞&#xff0c;这些漏洞可能被恶意攻击者利用&#xff0c;从而对用户的安全和隐私构成威胁。通过学习系统的登录和注册理解整个登录和注册的逻辑方便后续更好站在开发的角度思考问题发现漏洞。以下是一些常见…...

2024.7.29 刷题总结

2024.7.29 **每日一题** 682.棒球比赛&#xff0c;这道题是一道简单的模拟题&#xff0c;用栈模拟题中的四个操作就可以了&#xff0c;操作一是将x加到列表末尾&#xff0c;操作二是将列表的后两项之和加到列表末尾&#xff0c;操作三是把列表最后一项的两倍加到列表末尾&#…...

WebSocket程序设计

协议说明 WebSocket 是一种在单个TCP连接上进行全双工通信的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据。Websocket主要用在B/S架构的应用程序中&#xff0c;在 WebSocket API 中&#xff0c;浏览器和服务器只…...

ES(ElasticSearch)倒排索引

目录 正排与倒排索引 1.正排索引 作用&#xff1a; 优点&#xff1a; 缺点&#xff1a; 2.倒排索引 原理&#xff1a; 倒排索引的构建流程&#xff1a; 倒排索引的搜索流程&#xff1a; 优点&#xff1a; 缺点&#xff1a; 3. 应用场景 倒排索引中有几个非常重要的概念…...

Android Studio Build窗口出现中文乱码问题

刚安装成功的android studio软件打开工程&#xff0c;编译时下方build窗口中中文是乱码。 解决&#xff1a; 可点击studio状态栏的Help—>Edit Custom VM Options &#xff0c;在打开的studio64.exe.vmoptions文件后面添加&#xff1a;(要注意不能有空格&#xff0c;否则st…...

java生成随机数

代码 startValue 开始值 endValue 结束值 per生成的位数也就是精度 /*** 随机数的生成* param startValue* param endValue* return*/private BigDecimal randomBigDecimal(String startValue, String endValue,int per) {BigDecimal min new BigDecimal(startValue);BigDeci…...

动态定制深度学习:Mojo模型与自定义训练算法的无缝切换

动态定制深度学习&#xff1a;Mojo模型与自定义训练算法的无缝切换 引言 在机器学习领域&#xff0c;算法的选择对模型的性能有着决定性的影响。随着研究的深入和技术的发展&#xff0c;开发者可能需要根据不同的数据特性和业务需求&#xff0c;动态地切换或自定义训练算法。…...

昇思25天学习打卡营第19天|DCGAN生成漫画头像

DCGAN生成漫画头像总结 实验概述 本实验旨在利用深度卷积生成对抗网络&#xff08;DCGAN&#xff09;生成动漫头像&#xff0c;通过设置网络、优化器以及损失函数&#xff0c;使用MindSpore进行实现。 实验目的 学习和掌握DCGAN的基本原理和应用。熟悉使用MindSpore进行图像…...

排序题目:按照频率将数组升序排序

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;按照频率将数组升序排序 出处&#xff1a;1636. 按照频率将数组升序排序 难度 3 级 题目描述 要求 给定一个整数数组 nums \texttt{nums} nums&a…...

实分析与测度论问题的分类

实分析主要研究实数、实数序列、实数极限以及实值函数的分析&#xff0c;而度量空间则是一个具有距离函数的集合&#xff0c;其分类可以从多个角度进行。 实分析 实分析主要关注实数、实数序列、实数极限以及实值函数的分析。它涉及到多个重要的概念和理论&#xff0c;包括但…...

动态代理更改Java方法的返回参数(可用于优化feign调用后R对象的统一处理)

动态代理更改Java方法的返回参数&#xff08;可用于优化feign调用后R对象的统一处理&#xff09; 需求原始解决方案优化后方案1.首先创建AfterInterface.java2.创建InvocationHandler处理代理方法3. 调用 实际运行场景拓展 需求 某些场景&#xff0c;调用别人的方法&#xff0…...

Redis缓存数据库进阶——Redis与分布式锁(6)

分布式锁简介 1. 什么是分布式锁 分布式锁是一种在分布式系统环境下&#xff0c;通过多个节点对共享资源进行访问控制的一种同步机制。它的主要目的是防止多个节点同时操作同一份数据&#xff0c;从而避免数据的不一致性。 线程锁&#xff1a; 也被称为互斥锁&#xff08;Mu…...

网络芯片(又称为PHY网络芯片)

Realtek RTL8152B是一种常见的主板集成网络芯片&#xff08;又称为PHY网络芯片&#xff09;。PHY芯片是指将网络控制芯片的运算部分交由处理器或南桥芯片处理&#xff0c;以简化线路设计&#xff0c;从而降低成本。 https://www.realtek.com/Download/List?cate_id585 Realt…...

01 Go Web基础_20240728 课程笔记

概述 如果您没有Golang的基础&#xff0c;应该学习如下前置课程。 基础不好的同学每节课的代码最好配合视频进行阅读和学习&#xff0c;如果基础比较扎实&#xff0c;则阅读本教程巩固一下相关知识点即可&#xff0c;遇到不会的知识点再看视频。 视频课程 最近发现越来越多…...

嵌入式学习Day12---C语言提升

目录 一、指针数组 1.1.什么是指针数组 2.2. 格式 2.3.存储 2.4.与字符型二维数组相比 2.5.什么时候使用指针数组 2.6.练习 二、数组指针 2.1.什么是数组指针 2.2.格式 2.3.一维数组 2.3.特点 2.4.什么时候使用 三、指针和数组的关系 3.1.一维数组和指针 …...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Vite中定义@软链接

在webpack中可以直接通过符号表示src路径&#xff0c;但是vite中默认不可以。 如何实现&#xff1a; vite中提供了resolve.alias&#xff1a;通过别名在指向一个具体的路径 在vite.config.js中 import { join } from pathexport default defineConfig({plugins: [vue()],//…...

stm32wle5 lpuart DMA数据不接收

配置波特率9600时&#xff0c;需要使用外部低速晶振...