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

【数据结构】用C语言实现顺序栈(附完整运行代码)

🦄个人主页:修修修也

🎏所属专栏:数据结构

⚙️操作环境:Visual Studio 2022


一.了解项目功能

在本次项目中我们的目标是实现一个顺序栈:

顺序栈使用动态内存分配空间,可以用来存储任意数量的同类型数据.

顺序栈结构体需要包含三个要素:存放数据的数组arr,栈顶元素下标top,栈容量capacity.

顺序栈程序提供的功能有:

  1. 顺序栈的初始化
  2. 顺序栈的销毁
  3. 顺序栈的入栈
  4. 顺序栈的出栈
  5. 顺序栈的长度
  6. 顺序栈判空
  7. 顺序栈取栈顶元素

二.项目功能演示

要编写一个顺序栈项目,首先要明确我们想要达到的效果是什么样,下面我将用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语言实现顺序栈(附完整运行代码)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 一.了解项目功能 在本次项目中我们的目标是实现一个顺序栈: 该顺序栈使用动态内存分配空间,可以用来存储任意数量的同类型数据. 顺序栈结构体需要包含三个要素:存放数据的数组…...

鸿蒙(HarmonyOS)应用开发——生命周期、渲染控制、状态管理装饰器

生命周期 任何程序都是有一定的生命周期的。生命周期是记录从产生到销毁的过程&#xff1b;如果熟悉前端vue.js的话&#xff0c;就可以很好的理解生命周期。 自定义组件生命周期 ArkTS中&#xff0c;自定义组件提供了两个生命周期函数&#xff1a;aboutToAppear() 和aboutTo…...

yarn:无法加载文件 C:\Users\***\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本

原因&#xff1a;PowerShell 脚本的执行有着严格的安全策略限制&#xff01; 解决方案&#xff1a;管理员身份启动Windows PowerShell 在命令行中输入set-ExecutionPolicy RemoteSigned 再使用yarn就可以了...

精彩预告 | OpenHarmony即将亮相MTSC 2023

MTSC 2023 第12届中国互联网测试开发大会&#xff08;深圳站&#xff09;即将于2023年11月25日&#xff0c;在深圳登喜路国际大酒店举办&#xff0c;大会将以“1个主会场4个平行分会场”的形式呈现&#xff0c;聚集一众顶尖技术专家和行业领袖&#xff0c;围绕如今备受关注的行…...

无线WiFi安全渗透与攻防(国外篇):使用 Aircrack-ng 破解 WEP 密码

使用 Aircrack-ng 破解 WEP 密码 使用 Aircrack-ng 破解 WEP 密码一. 用 Aircrack-ng 破解 WEP 密码 - 背景知识网卡与网卡芯片WEP 加密协议WEP 所使用的身份认证协议二. 使用 Aircrack-ng 破解 WEP 密码 - 破解原理破解机理三. 使用 Aircrack-ng 破解 WEP 密码 - aircrack-ng …...

广告机/商业显示屏_基于MT8788安卓主板方案

安卓主板在广告机领域扮演着重要的角色。无论是在商场、车站、酒店、电梯、机场还是高铁站&#xff0c;LED广告机广泛应用&#xff0c;并通过不同方式进行播放和管理。 广告机/商业显示屏_基于MT8788安卓主板方案 基于MT8788安卓主板方案的广告机采用了联发科MT8788八核芯片方案…...

字符串转换成十进制整数

编程要求 输入一个以#结束的字符串&#xff0c;本题要求滤去所有的非十六进制字符&#xff08;不分大小写&#xff09;&#xff0c;组成一个新的表示十六进制数字的字符串&#xff0c;然后将其转换为十进制数后输出。如果在第一个十六进制字符之前存在字符“-”&#xff0c;则…...

面向对象高级---接口

接口 概念:接口就是一种公共的规范标准,只要符合规范,大家都可以通用 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...重命名所有文件夹里的文件

最新&#xff1a; 最快方法&#xff1a;先用这个教程http://文件重命名1,2......nhttps://jingyan.baidu.com/article/495ba841281b7079b20ede2c.html再用这个教程去空格&#xff1a;利用批处理去掉文件名中的空格-百度经验 (baidu.com) 以下为原回答 注意文件名有空格会失败…...

你知道吗,这些行业的人也是工程师哦

止这些&#xff0c;其工作涉及多种领域&#xff0c;也就是说&#xff0c;有很多细分行业的开发人员也算是电子工程师&#xff0c;下面我们来看看有哪些电子工程师&#xff01; 1、应用电子工程师 主要负责将电子技术与特定应用相结合&#xff0c;设计并开发满足特定需求的电子…...

1.6 C语言之数组概述

1.6 C语言之数组概述 一、数组二、练习 一、数组 所谓数组&#xff0c;就是内存中一片连续的空间&#xff0c;可以用来存储一组同类型的数据 数组有下标&#xff0c;从0开始&#xff0c;可以理解为是给数组中的元素编号&#xff0c;便于后续寻址访问 我们来编写一个程序&…...

论文阅读_生成式Agent

英文名称: Generative Agents: Interactive Simulacra of Human Behavior 中文名称: 生成代理&#xff1a;**人类行为的交互式模拟** 文章: http://arxiv.org/abs/2304.03442 代码: https://github.com/joonspk-research/generative_agents 作者: Joon Sung Park 机构: 斯坦福大…...

uniapp时间选择器

Uniapp 是一套基于Vue.js 开发的跨平台开发框架&#xff0c;它能够以一套代码编译成多个平台的应用&#xff0c;包括 iOS、Android、H5 等。要实现时间选择器可以使用uni-app提供的组件picker&#xff0c;它可以用于选择器、时间选择器、日期选择器等场景。 以下是一个简单的时…...

2017年3月24日 Go生态洞察:HTTP/2服务器推送技术深度解析

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

x86 汇编语言介绍001

1&#xff0c;搭建编程环境 1.1 NASM 基本信息 示例使用的汇编器为 nasm 主页&#xff1a; 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

一、语音合成概述 语音信号的产生分为两个阶段&#xff0c;信息编码和生理控制。首先在大脑中出现某种想要表达的想法&#xff0c;然后由大脑将其编码为具体的语言文字序列&#xff0c;及语音中可能存在的强调、重读等韵律信息。经过语言的组织&#xff0c;大脑通过控制发音器…...

Docker+ Jenkins+Maven+git自动化部署

环境&#xff1a;Centos7 JDK1.8 Maven3.3.9 Git 2.40 Docker 20.10.17 准备工作&#xff1a; 安装Docker Centos7默认的yum安装的docker是1.13&#xff0c;版本太低&#xff0c;很多镜像都要Docker版本要求&#xff0c;升级Docker版本。 卸载已安装Docker: yum …...

MySQL- 创建可以远程访问的root账户

创建用户 默认的root用户只能当前节点localhost访问&#xff0c;是无法远程访问的&#xff0c;所以&#xff0c;我们要创建一个root账户&#xff0c;帮助用户远程访问。 create user root% IDENTIFIED WITH mysql_native_password BY 1234;这个命令是在MySQL数据库管理系统中…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

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

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

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...