【数据结构】用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数据库管理系统中…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
Java 语言特性(面试系列1)
一、面向对象编程 1. 封装(Encapsulation) 定义:将数据(属性)和操作数据的方法绑定在一起,通过访问控制符(private、protected、public)隐藏内部实现细节。示例: public …...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Spring Boot面试题精选汇总
🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...



