【数据结构】用C语言实现顺序栈(附完整运行代码)
🦄个人主页:修修修也
🎏所属专栏:数据结构
⚙️操作环境:Visual Studio 2022

一.了解项目功能
在本次项目中我们的目标是实现一个顺序栈:
该顺序栈使用动态内存分配空间,可以用来存储任意数量的同类型数据.
顺序栈结构体需要包含三个要素:存放数据的数组arr,栈顶元素下标top,栈容量capacity.
顺序栈程序提供的功能有:
- 顺序栈的初始化
- 顺序栈的销毁
- 顺序栈的入栈
- 顺序栈的出栈
- 顺序栈的长度
- 顺序栈判空
- 顺序栈取栈顶元素
二.项目功能演示
要编写一个顺序栈项目,首先要明确我们想要达到的效果是什么样,下面我将用vs2022编译器来为大家演示一下顺序栈程序运行时的样子:
顺序栈的C语言实现
三.逐步实现项目功能模块及其逻辑详解
通过第二部分对项目功能的介绍,我们已经对顺序栈的功能有了大致的了解,虽然看似需要实现的功能很多,貌似一时间不知该如何下手,但我们可以分步分模块来分析这个项目的流程,最后再将各部分进行整合,所以大家不用担心,跟着我一步一步分析吧!
!!!注意,该部分的代码只是为了详细介绍某一部分的项目实现逻辑,故可能会删减一些与该部分不相关的代码以便大家理解,需要查看或拷贝完整详细代码的朋友可以移步本文第四部分。
1.实现顺序栈程序菜单
菜单部分的逻辑比较简单,就是利用C语言printf函数打印出这个菜单界面即可。但要注意菜单的标序要和后续switch...case语句的分支相应,以免导致后续执行语句错乱的问题.基础问题就不过多赘述了,代码如下:
该部分功能实现代码如下:
void STMenu()
{printf("**********************************\n");printf("******请选择要进行的操作 ******\n");printf("******1.顺序栈入栈 ******\n");printf("******2.顺序栈出栈 ******\n");printf("******3.取栈顶元素 ******\n");printf("******4.判断栈空 ******\n");printf("******5.查询当前栈长 ******\n");printf("******6.清空顺序栈 ******\n");printf("******7.销毁顺序栈 ******\n");printf("******0.退出顺序栈程序 ******\n");printf("**********************************\n");printf("请选择:>");}
2.实现顺序栈程序功能可循环使用
由于我们要实现顺序栈的功能可以反复使用的逻辑,且至少在一开始执行一次,因此我们选择do...while的循环语句来实现这一部分的逻辑.
该部分功能实现代码如下:
int main()
{ST st;STInit(&st);int swi = 0;//创建变量swi作为do...while循环的终止条件,以及switch语句的运行条件do //使用do...while实现{STMenu();scanf("%d", &swi);switch (swi){case 0:STDestroy(&st);printf("您已退出程序:>\n");// 释放链表内存break;case 1:printf("请输入要入栈的数据:>");STDataType pushback_data = 0;scanf("%d", &pushback_data);STPush(&st, pushback_data);printf("已成功入栈:>\n");break;case 2:printf("栈顶元素%d已成功出栈\n", STTop(&st));STPop(&st);break;case 3:printf("栈顶元素为:");STDataType sttop = STTop(&st);printf("%d\n", sttop);break;case 4:if (!STEmpty(&st)){printf("当前栈不为空\n");}else{printf("当前栈为空栈\n");}break;case 5:printf("当前栈长为:");int stsize = STSize(&st);printf("%d\n", stsize);break;case 6:STDestroy(&st);STInit(&st);printf("顺序栈已清空:>\n");break;case 7:STDestroy(&st);printf("顺序栈已销毁:>\n");break;default:printf("输入错误,请重新输入\n");break;}} while (swi);return 0;
}
3.创建顺序栈
创建顺序栈成员的结构体应该包括:存放数据的数组arr,栈顶元素下标top,栈容量capacity.
因此我们创建Stack结构体类型时应由一个数组及两个整型组成.
这里的第9行使用的typedef类定义的作用是方便我们后续在使用顺序栈时对存储的数据类型做更改,比如后续我们不想存储int类型数据了,就可以很方便的在这里对数组类型做更改.比如改成char类型,或者double类型,甚至改成任意自己构造的结构类型.
综上,该部分代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;typedef struct Stack
{int *arr;int top;int capacity;
}ST;
4.初始化顺序栈
初始化顺序栈的逻辑和初始化顺序表一样,我们在初始化时为栈开辟4个数据类型的数组空间,然后将顺序栈的容量改为4,栈顶置为0即可.
该部分的功能实现代码如下:
void STInit(ST* ps)
{assert(ps);ps->arr = (STDataType*)malloc(sizeof(STDataType) * 4);if (ps->arr == NULL){perror("malloc fail::\n");return;}ps->capacity = 4;ps->top = 0; //top表示栈顶元素的下一个//top指向栈顶元素的话,top给-1}
5.顺序栈的入栈
顺序栈在入栈时,需要先判断一下栈内元素是否已满,如果满了则需要给栈扩容.(如下代码5-18行均是在执行顺序栈查满扩容逻辑)
如果没满则将新元素赋值给栈顶指针top,再将top++,使其始终指向栈顶的下一个元素位置.
该部分的功能实现代码如下:
void STPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity)//扩容{STDataType* tmp = (STDataType*)realloc(ps->arr, sizeof(STDataType) * ps->capacity * 2);if (tmp == NULL){perror("realloc fail::\n");return;}ps->arr = tmp;ps->capacity *= 2;}ps->arr[ps->top] = x;ps->top++;}
6.顺序栈的出栈
顺序栈的出栈就相当于顺序表的尾删,那么我们同顺序表一样移动栈顶下标位置即可.
顺序表尾删示意图:
该部分的功能实现代码如下:
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}
7.顺序栈取栈顶元素
根据我们之前的设定,栈为空时top=0:
那么当栈中进入一个元素时,top++后top=1,而栈顶元素a1的下标等于0,所以我们的top设计其实是指向栈顶元素的下一个位置的:
因此在取栈顶函数中,我们要返回的栈顶数组下标应该是top-1.
该部分的功能实现代码如下:
STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->arr[ps->top - 1];
}
8.顺序栈的长度
因为top指向的是栈顶元素的下一个位置,因此top的大小正好是栈的长度,所以求栈长函数我们对ps断言后可以直接返回top.
该部分的功能实现代码如下:
int STSize(ST* ps)
{assert(ps);return ps->top;
}
9.顺序栈的判空
顺序栈判空的逻辑是:如果栈为空返回true(真),否则返回false(假).
因此我们还是拿top来判断,如果top=0,会return true,意味着栈为空.
否则会return false,意味着栈不为空.
该部分的功能实现代码如下:
bool STEmpty(ST* ps)//判空,为空则真
{assert(ps);return ps->top==0;
}
10.顺序栈的销毁
当我们使用完顺序栈想要退出程序时,就应该将之前动态开辟的内存释放掉,还给操作系统.即销毁顺序栈.
我们使用free()函数释放掉之前动态开辟的数组arr,然后将arr置为空指针,最后将top,capacity的值置为0即可.
该部分的功能实现代码如下:
void STDestroy(ST* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->top = 0;ps->capacity = 0;}
四.项目完整代码
我们将程序运行的代码分别在三个工程文件中编辑,完整代码如下:
test.c文件
#include"Stack.h"int main()
{ST st;STInit(&st);int swi = 0;//创建变量swi作为do...while循环的终止条件,以及switch语句的运行条件do //使用do...while实现{STMenu();scanf("%d", &swi);switch (swi){case 0:STDestroy(&st);printf("您已退出程序:>\n");// 释放链表内存break;case 1:printf("请输入要入栈的数据:>");STDataType pushback_data = 0;scanf("%d", &pushback_data);STPush(&st, pushback_data);printf("已成功入栈:>\n");break;case 2:printf("栈顶元素%d已成功出栈\n", STTop(&st));STPop(&st);break;case 3:printf("栈顶元素为:");STDataType sttop = STTop(&st);printf("%d\n", sttop);break;case 4:if (!STEmpty(&st)){printf("当前栈不为空\n");}else{printf("当前栈为空栈\n");}break;case 5:printf("当前栈长为:");int stsize = STSize(&st);printf("%d\n", stsize);break;case 6:STDestroy(&st);STInit(&st);printf("顺序栈已清空:>\n");break;case 7:STDestroy(&st);printf("顺序栈已销毁:>\n");break;default:printf("输入错误,请重新输入\n");break;}} while (swi);return 0;
}
Stack.c 文件
#include"Stack.h"void STInit(ST* ps)
{assert(ps);ps->arr = (STDataType*)malloc(sizeof(STDataType) * 4);if (ps->arr == NULL){perror("malloc fail::\n");return;}ps->capacity = 4;ps->top = 0; //top表示栈顶元素的下一个//top指向栈顶元素的话,top给-1}void STDestroy(ST* ps)
{assert(ps);free(ps->arr);ps->arr = NULL;ps->top = 0;ps->capacity = 0;}void STPush(ST* ps, STDataType x)
{assert(ps);if (ps->top == ps->capacity)//扩容{STDataType* tmp = (STDataType*)realloc(ps->arr,sizeof(STDataType)*ps->capacity*2);if (tmp == NULL){perror("realloc fail::\n");return;}ps->arr = tmp;ps->capacity *= 2;}ps->arr[ps->top] = x;ps->top++;}void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}int STSize(ST* ps)
{assert(ps);return ps->top;
}bool STEmpty(ST* ps)//判空,为空则真
{assert(ps);return ps->top==0;
}STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->arr[ps->top - 1];
}void STMenu()
{printf("**********************************\n");printf("******请选择要进行的操作 ******\n");printf("******1.顺序栈入栈 ******\n");printf("******2.顺序栈出栈 ******\n");printf("******3.取栈顶元素 ******\n");printf("******4.判断栈空 ******\n");printf("******5.查询当前栈长 ******\n");printf("******6.清空顺序栈 ******\n");printf("******7.销毁顺序栈 ******\n");printf("******0.退出顺序栈程序 ******\n");printf("**********************************\n");printf("请选择:>");
}
Stack.h文件
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;typedef struct Stack
{int *arr;int top;int capacity;
}ST;void STInit(ST* ps);
void STDestroy(ST* ps);void STPush(ST* ps, STDataType x);
void STPop(ST* ps);int STSize(ST* ps);bool STEmpty(ST* ps);//判空,为空则真STDataType STTop(ST* ps);void STMenu();
结语
希望这篇顺序栈的C语言实现详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.
学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!
相关文章推荐
【数据结构】什么是栈?
【数据结构】C语言实现顺序表万字详解(附完整运行代码)
【数据结构】C语言实现单链表万字详解(附完整运行代码)
【数据结构】C语言实现带头双向循环链表万字详解(附完整运行代码)
【实用编程技巧】不想改bug?初学者必须学会使用的报错函数assert!(断言函数详解)

数据结构栈与队列篇思维导图:

相关文章:
【数据结构】用C语言实现顺序栈(附完整运行代码)
🦄个人主页:修修修也 🎏所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 一.了解项目功能 在本次项目中我们的目标是实现一个顺序栈: 该顺序栈使用动态内存分配空间,可以用来存储任意数量的同类型数据. 顺序栈结构体需要包含三个要素:存放数据的数组…...
鸿蒙(HarmonyOS)应用开发——生命周期、渲染控制、状态管理装饰器
生命周期 任何程序都是有一定的生命周期的。生命周期是记录从产生到销毁的过程;如果熟悉前端vue.js的话,就可以很好的理解生命周期。 自定义组件生命周期 ArkTS中,自定义组件提供了两个生命周期函数:aboutToAppear() 和aboutTo…...
yarn:无法加载文件 C:\Users\***\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本
原因:PowerShell 脚本的执行有着严格的安全策略限制! 解决方案:管理员身份启动Windows PowerShell 在命令行中输入set-ExecutionPolicy RemoteSigned 再使用yarn就可以了...
精彩预告 | OpenHarmony即将亮相MTSC 2023
MTSC 2023 第12届中国互联网测试开发大会(深圳站)即将于2023年11月25日,在深圳登喜路国际大酒店举办,大会将以“1个主会场4个平行分会场”的形式呈现,聚集一众顶尖技术专家和行业领袖,围绕如今备受关注的行…...
无线WiFi安全渗透与攻防(国外篇):使用 Aircrack-ng 破解 WEP 密码
使用 Aircrack-ng 破解 WEP 密码 使用 Aircrack-ng 破解 WEP 密码一. 用 Aircrack-ng 破解 WEP 密码 - 背景知识网卡与网卡芯片WEP 加密协议WEP 所使用的身份认证协议二. 使用 Aircrack-ng 破解 WEP 密码 - 破解原理破解机理三. 使用 Aircrack-ng 破解 WEP 密码 - aircrack-ng …...
广告机/商业显示屏_基于MT8788安卓主板方案
安卓主板在广告机领域扮演着重要的角色。无论是在商场、车站、酒店、电梯、机场还是高铁站,LED广告机广泛应用,并通过不同方式进行播放和管理。 广告机/商业显示屏_基于MT8788安卓主板方案 基于MT8788安卓主板方案的广告机采用了联发科MT8788八核芯片方案…...
字符串转换成十进制整数
编程要求 输入一个以#结束的字符串,本题要求滤去所有的非十六进制字符(不分大小写),组成一个新的表示十六进制数字的字符串,然后将其转换为十进制数后输出。如果在第一个十六进制字符之前存在字符“-”,则…...
面向对象高级---接口
接口 概念:接口就是一种公共的规范标准,只要符合规范,大家都可以通用 java中接口存在的两个意义 用来定义规范用来做功能的扩展 接口的特点 接口用关键字interface修饰 public interface 接口名{}类实现接口用implements表示 public class 类名 implements 接口名{}接口…...
轻松入门自然语言处理系列 项目3 基于Linear-CRF的医疗实体识别
文章目录 前言一、项目概况1.项目描述2.数据描述3.项目框架二、核心技术1.实体识别数据标注2.文本特征工程3.CRF模型4.BiLSTM-CRF模型三、项目实施1.读取数据2.数据标注3.文本特征工程4.模型训练5.模型评估6.BiLSTM-CRF总结前言 本文主要介绍了以Linear-CRF为基础模型进行医疗…...
批量按顺序1、2、3...重命名所有文件夹里的文件
最新: 最快方法:先用这个教程http://文件重命名1,2......nhttps://jingyan.baidu.com/article/495ba841281b7079b20ede2c.html再用这个教程去空格:利用批处理去掉文件名中的空格-百度经验 (baidu.com) 以下为原回答 注意文件名有空格会失败…...
你知道吗,这些行业的人也是工程师哦
止这些,其工作涉及多种领域,也就是说,有很多细分行业的开发人员也算是电子工程师,下面我们来看看有哪些电子工程师! 1、应用电子工程师 主要负责将电子技术与特定应用相结合,设计并开发满足特定需求的电子…...
1.6 C语言之数组概述
1.6 C语言之数组概述 一、数组二、练习 一、数组 所谓数组,就是内存中一片连续的空间,可以用来存储一组同类型的数据 数组有下标,从0开始,可以理解为是给数组中的元素编号,便于后续寻址访问 我们来编写一个程序&…...
论文阅读_生成式Agent
英文名称: Generative Agents: Interactive Simulacra of Human Behavior 中文名称: 生成代理:**人类行为的交互式模拟** 文章: http://arxiv.org/abs/2304.03442 代码: https://github.com/joonspk-research/generative_agents 作者: Joon Sung Park 机构: 斯坦福大…...
uniapp时间选择器
Uniapp 是一套基于Vue.js 开发的跨平台开发框架,它能够以一套代码编译成多个平台的应用,包括 iOS、Android、H5 等。要实现时间选择器可以使用uni-app提供的组件picker,它可以用于选择器、时间选择器、日期选择器等场景。 以下是一个简单的时…...
2017年3月24日 Go生态洞察:HTTP/2服务器推送技术深度解析
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...
x86 汇编语言介绍001
1,搭建编程环境 1.1 NASM 基本信息 示例使用的汇编器为 nasm 主页: https://www.nasm.us/https://www.nasm.us/ 下载最新的稳定版源代码 wget https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/nasm-2.16.01.tar.gz 1.2解压并编译安装 tar zx…...
Oracle(2-5)Usage and Configuration of the Oracle Shared Server
文章目录 一、基础知识1、 Server Configurations服务器配置2、Dedicated server process专用服务器进程3、Oracle Shared ServerOracle共享服务器4、Benefits of Shared Server 共享服务器的优点5、Processing a Request 处理请求6、Configuring Shared Server 配置共享服务器…...
语音合成综述Speech Synthesis
一、语音合成概述 语音信号的产生分为两个阶段,信息编码和生理控制。首先在大脑中出现某种想要表达的想法,然后由大脑将其编码为具体的语言文字序列,及语音中可能存在的强调、重读等韵律信息。经过语言的组织,大脑通过控制发音器…...
Docker+ Jenkins+Maven+git自动化部署
环境:Centos7 JDK1.8 Maven3.3.9 Git 2.40 Docker 20.10.17 准备工作: 安装Docker Centos7默认的yum安装的docker是1.13,版本太低,很多镜像都要Docker版本要求,升级Docker版本。 卸载已安装Docker: yum …...
MySQL- 创建可以远程访问的root账户
创建用户 默认的root用户只能当前节点localhost访问,是无法远程访问的,所以,我们要创建一个root账户,帮助用户远程访问。 create user root% IDENTIFIED WITH mysql_native_password BY 1234;这个命令是在MySQL数据库管理系统中…...
告别双系统!用VMware把Ubuntu 20.10装进移动硬盘,打造随身开发环境
随身开发环境实战:用VMware将Ubuntu 20.10部署至移动硬盘的全方位指南 在咖啡厅调试代码时发现环境配置丢失,回家后又要重新配置依赖——这可能是开发者最头疼的场景之一。将完整开发环境塞进口袋随身携带,正成为越来越多技术工作者的刚性需求…...
Flutter集成华为厂商推送全攻略:解决后台被杀收不到消息的终极方案
Flutter集成华为厂商推送全攻略:解决后台被杀收不到消息的终极方案 在移动应用开发中,推送通知是保持用户活跃度的关键功能。然而,许多Flutter开发者在使用极光推送时都会遇到一个棘手问题:在华为手机上,当应用后台进…...
虚拟世界不再需要“用户”,只需要“意识锚点”?——2026奇点大会最震撼闭门议题首次对外解密
第一章:虚拟世界不再需要“用户”,只需要“意识锚点”?——2026奇点大会最震撼闭门议题首次对外解密 2026奇点智能技术大会(https://ml-summit.org) 从身份认证到意识注册:范式迁移的临界点 传统数字身份体系正遭遇根本性失效&a…...
PoeCharm:10个技巧让你成为流放之路角色构建大师
PoeCharm:10个技巧让你成为流放之路角色构建大师 【免费下载链接】PoeCharm Path of Building Chinese version 项目地址: https://gitcode.com/gh_mirrors/po/PoeCharm 当你在流放之路中面对复杂的角色构建时,是否曾因语言障碍而错过最佳装备组合…...
C#连接OPC UA服务器的三种身份验证方式详解:匿名、用户名密码和证书(附完整代码)
C#连接OPC UA服务器的三种身份验证方式详解:匿名、用户名密码和证书(附完整代码) 在工业自动化领域,数据安全传输一直是系统集成中的核心挑战。OPC UA作为新一代工业通信标准,其安全机制设计尤为关键。本文将深入解析三…...
AGI不是工具,而是对手:揭秘某国家级红队用LLM+AGI协同实施APT29变种攻击的完整TTPs链条
第一章:AGI作为新型对抗主体的范式跃迁 2026奇点智能技术大会(https://ml-summit.org) 传统网络安全对抗模型长期基于“人—工具—系统”三级结构,攻击者为人类或其代理程序(如自动化脚本、Botnet),防御方亦以人类策…...
【Allegro 17.4 实战指南】布线后DRC检查与工艺优化全解析
1. Allegro 17.4布线后DRC检查全流程 刚完成PCB布线的新手工程师经常会遇到这样的困惑:明明布线时已经小心翼翼,为什么投板生产后还是会出现各种问题?其实布线完成只是PCB设计的第一步,后续的DRC检查和工艺优化才是确保设计可靠性…...
手把手教你玩转WS2812B灯带:基于STM32 HAL库的PWM+DMA驱动教程(CubeMX配置)
STM32CubeMX实战:HAL库驱动WS2812B灯带的PWMDMA全流程解析 在智能硬件和物联网项目中,RGB LED灯带因其丰富的色彩表现和灵活的编程特性,成为提升产品交互体验的热门选择。而WS2812B作为集成控制电路与发光元件的智能外设,仅需单线…...
保姆级教程:用Unity把原神角色变成你的专属桌宠(附完整C#脚本)
Unity实战:打造高互动性原神风格桌宠全流程指南 从零开始构建你的虚拟伙伴 在数字生活日益丰富的今天,个性化桌面伴侣已成为许多用户表达自我风格的方式。想象一下,当你工作疲惫时,桌面上可爱的游戏角色会对你眨眼;当你…...
GAT1400跨级订阅避坑指南:从‘上下级’关系到稳定接收通知的完整配置
GAT1400跨级订阅实战解析:构建稳定多级视图库通信网络 在公安、交通等行业的视频监控系统集成中,GAT1400标准已成为实现多级平台数据共享的技术基石。作为系统集成工程师,我们常常需要面对A、B、C三级甚至更多层级平台间的复杂订阅关系配置。…...



