C语言_数据结构总结5:顺序栈

news2025/3/9 8:25:17

纯C语言代码,不涉及C++

想了解链式栈的实现,欢迎查看这篇文章:C语言_数据结构总结6:链式栈-CSDN博客

这里分享插入一下个人觉得很有用的习惯:

1. 就是遇到代码哪里不理解的,你就问豆包,C知道,Kimi等等AI工具,比如在这栈中你不能理解为什么有时候要传一级指针有时候又不用,你就询问AI“在进栈操作中是否可以不传入指针变量,而是直接传入结构体变量”;

2. 还有就是自己的代码报错了,又或是自己觉得自己的代码存在某种问题,而自己又不能解决时,你就直接复制自己的代码问AI,让AI对以下代码进行点评,并返回改善后的代码。

前言

:是只允许在一端进行插入或删除操作的线性表。
栈顶:允许进行插入或删除的那一端
栈底:固定的,不允许进行插入或删除的那一端
栈的特性后进先出
存储方式:1. 顺序存储(顺序栈)  2. 链式存储(链式栈)

       在顺序栈的基本操作中,决定是传入一级指针还是只传入栈的变量,主要取决于操作是否需要修改栈的内部状态
    1. 需要传入一级指针的情况
    当操作需要修改栈的内部状态,比如改变栈顶指针 top 的值或者修改栈中存储的数据时,就需要传入一级指针。
    这是因为在 C 语言里,函数参数传递是值传递,若直接传入栈的变量,函数内部对该变量的修改不会影响到原变量。
    而通过传入指针,函数可以直接访问和修改原变量所指向的内存。

    2. 只需要传入栈的变量的情况
    当操作不需要修改栈的内部状态,仅仅是读取栈的信息时,就可以只传入栈的变量。

以下是顺序栈实现
它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针top指示当前的栈顶元素的位置

0. 结构单元

#define MaxSize 50
typedef int ElemType;
typedef struct SqStack {
    ElemType data[MaxSize];  //存放栈中元素
    int top;  //栈顶指针
}SqStack;

!注意  :栈顶指针top,它不是实际意义上的指针变量,进行存放指针变量。这里说它是指针,意思是说,它指示了当前栈顶元素的位置,在第pos个位置。

1. 初始化

void InitSeqStack(SqStack* s) {
	s->top = -1;  //初始化栈顶的位置
}

这里设置初始栈顶指针s.top = -1,
栈空条件是s.top = -1;栈满条件是s.top = MaxSize - 1
则进栈时指针s.top+1,再将元素加入栈顶;出栈时先取出栈顶元素,后指针s.top - 1

但如果设置初始栈顶指针s.top = 0,
栈空条件是s.top = 0;栈满条件是s.top = MaxSize
则进栈时将元素加入栈顶,再指针s.top+1;出栈时先指针s.top - 1,后取出栈顶元素

2. 判空

int SqStackEmpty(SqStack s) {
	return s.top == -1;
}

3. 判满

int SqStackFull(SqStack s) {
	return s.top == MaxSize - 1;
}

4. 入栈

即:将元素加入到栈顶

int push(SqStack* s, ElemType value) {
	// 1. 判满
	if (SqStackFull(*s))
	{
		printf("栈满,无法入栈!\n");
		return -2;
	}
	// 2. 指针top + 1,再将值加入到栈顶
	s->top++;
	s->data[s->top] = value;
	return 0;  //入栈成功
}

5. 出栈

int pop(SqStack* s, ElemType* value) {
	//1. 判空
	if (SqStackEmpty(*s))
	{
		printf("栈空,无法有元素出栈!\n");
		return -1;
	}
	//2. 先取出栈顶元素,再指针top - 1
	*value = s->data[s->top];
	s->top--;
	return 0;  //出栈成功
}

6. 获取栈顶元素

int getTop(SqStack s,ElemType *value) {
	//1. 判空
	if (SqStackEmpty(s))
	{
		printf("栈空,无法有元素出栈!\n");
		return -1;
	}
	//2. 获取栈顶元素
	*value = s.data[s.top];
	return 0;  
}

7. 打印栈中元素

void printSqStack(SqStack s) {
	if (SqStackEmpty(s))
	{
		printf("栈空!\n");
		return;  //提前结束该函数
	}
	printf("栈中的元素(从栈底到栈顶)为: ");
	for (int i = 0; i <= s.top; i++) {
		printf("%d ", s.data[i]);
	}
	printf("\n");
}

8. 销毁

void destroySqStack(SqStack* s) {
	// 由于顺序栈使用的是静态数组,不需要显式释放内存
	// 只需要将栈顶指针置为 -1 表示栈为空
	s->top = -1;
}

9. 测试

int main() {
	SqStack s;
	InitSeqStack(&s);

	// 测试入栈操作
	push(&s, 11);
	push(&s, 22);
	push(&s, 33);
	printSqStack(s);  // 栈中的元素(从栈底到栈顶)为: 11 22 33

	// 获取栈顶元素
	ElemType value;
	if (getTop(s,&value) == 0)
	{
		printf("当前栈顶元素为:%d\n", value); // 当前栈顶元素为:33
	}

	//测试出栈操作
	if (pop(&s,&value) == 0)
	{
		printf("出栈的元素为:%d\n", value);  // 出栈的元素为:33
	}
	printSqStack(s);  // 栈中的元素(从栈底到栈顶)为: 11 22

	//销毁栈
	destroySqStack(&s);
	printSqStack(s);  // 栈空!

	return 0;
}

10. 完整代码

#include<stdio.h>
#include<stdlib.h>
/*
	栈:是只允许在一端进行插入或删除操作的线性表。
	栈顶:允许进行插入或删除的那一端
	栈底:固定的,不允许进行插入或删除的那一端
	栈的特性:后进先出
	存储方式:1. 顺序存储(顺序栈)  2. 链式存储(链式栈)
*/

/*
    在顺序栈的基本操作中,决定是传入一级指针还是只传入栈的变量,主要取决于操作是否需要修改栈的内部状态。
	1. 需要传入一级指针的情况
	当操作需要修改栈的内部状态,比如改变栈顶指针 top 的值或者修改栈中存储的数据时,就需要传入一级指针。
	这是因为在 C 语言里,函数参数传递是值传递,若直接传入栈的变量,函数内部对该变量的修改不会影响到原变量。
	而通过传入指针,函数可以直接访问和修改原变量所指向的内存。

	2. 只需要传入栈的变量的情况
	当操作不需要修改栈的内部状态,仅仅是读取栈的信息时,就可以只传入栈的变量。

*/

/*
   以下是顺序栈实现
   它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针top指示当前的栈顶元素的位置
*/


#define MaxSize 50
typedef int ElemType;
typedef struct SqStack {
	ElemType data[MaxSize];  //存放栈中元素
	int top;  //栈顶指针(注意,它不是实际意义上的指针变量,进行存放指针变量。这里说它是指针,意思是说,它指示了当前栈顶元素的位置,在第pos个位置。
}SqStack;

// 操作1——初始化
void InitSeqStack(SqStack* s) {
	s->top = -1;  //初始化栈顶的位置
}

/*
    这里设置初始栈顶指针s.top = -1,
	栈空条件是s.top = -1;栈满条件是s.top = MaxSize - 1
	则进栈时指针s.top+1,再将元素加入栈顶;出栈时先取出栈顶元素,后指针s.top - 1
	
	但如果设置初始栈顶指针s.top = 0,
	栈空条件是s.top = 0;栈满条件是s.top = MaxSize
	则进栈时将元素加入栈顶,再指针s.top+1;出栈时先指针s.top - 1,后取出栈顶元素	
*/

// 操作2——判空
int SqStackEmpty(SqStack s) {
	return s.top == -1;
}

// 操作3——判满
int SqStackFull(SqStack s) {
	return s.top == MaxSize - 1;
}

// 操作4——入栈,将元素加到栈顶
int push(SqStack* s, ElemType value) {
	// 1. 判满
	if (SqStackFull(*s))
	{
		printf("栈满,无法入栈!\n");
		return -2;
	}
	// 2. 指针top + 1,再将值加入到栈顶
	s->top++;
	s->data[s->top] = value;
	return 0;  //入栈成功
}

// 操作5——出栈
int pop(SqStack* s, ElemType* value) {
	//1. 判空
	if (SqStackEmpty(*s))
	{
		printf("栈空,无法有元素出栈!\n");
		return -1;
	}
	//2. 先取出栈顶元素,再指针top - 1
	*value = s->data[s->top];
	s->top--;
	return 0;  //出栈成功
}

// 操作6——获取栈顶元素
int getTop(SqStack s,ElemType *value) {
	//1. 判空
	if (SqStackEmpty(s))
	{
		printf("栈空,无法有元素出栈!\n");
		return -1;
	}
	//2. 获取栈顶元素
	*value = s.data[s.top];
	return 0;  
}

// 操作7——打印栈中元素
void printSqStack(SqStack s) {
	if (SqStackEmpty(s))
	{
		printf("栈空!\n");
		return;  //提前结束该函数
	}
	printf("栈中的元素(从栈底到栈顶)为: ");
	for (int i = 0; i <= s.top; i++) {
		printf("%d ", s.data[i]);
	}
	printf("\n");
}

// 操作8——销毁栈
void destroySqStack(SqStack* s) {
	// 由于顺序栈使用的是静态数组,不需要显式释放内存
	// 只需要将栈顶指针置为 -1 表示栈为空
	s->top = -1;
}

int main() {
	SqStack s;
	InitSeqStack(&s);

	// 测试入栈操作
	push(&s, 11);
	push(&s, 22);
	push(&s, 33);
	printSqStack(s);  // 栈中的元素(从栈底到栈顶)为: 11 22 33

	// 获取栈顶元素
	ElemType value;
	if (getTop(s,&value) == 0)
	{
		printf("当前栈顶元素为:%d\n", value); // 当前栈顶元素为:33
	}

	//测试出栈操作
	if (pop(&s,&value) == 0)
	{
		printf("出栈的元素为:%d\n", value);  // 出栈的元素为:33
	}
	printSqStack(s);  // 栈中的元素(从栈底到栈顶)为: 11 22

	//销毁栈
	destroySqStack(&s);
	printSqStack(s);  // 栈空!

	return 0;
}

11. 运行截图

本人菜鸟一只,文章如有出错处,欢迎评论区指正!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2312044.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人工智能之数学基础:正交矩阵

本文重点 正交矩阵是线性代数中一个重要的特殊矩阵&#xff0c;它在许多领域都有广泛的应用。 什么是正交矩阵 如图所示&#xff0c;当矩阵A满足如上所示的条件的时候&#xff0c;此时我们就可以认为是正交矩阵&#xff0c;需要注意一点矩阵A必为方阵。 正交矩阵的充要条件 …

抓包分析工具介绍

什么是抓包分析工具&#xff1f; 抓包分析工具&#xff0c;也称为网络数据包嗅探器或协议分析器&#xff0c;用于捕获和检查网络上传输的数据包。这些数据包包含了网络通信的详细信息&#xff0c;例如请求的资源、服务器的响应、HTTP 头信息、传输的数据内容等等。通过分析这些…

2025/3/8 第 27 场 蓝桥入门赛 题解

1. 38红包【算法赛】 签到题&#xff1a; 算倍数就行了 #include <bits/stdc.h> using namespace std; int main() {int ans0;for(int i1;i<2025;i){if(i % 3 0)ans;else if(i % 8 0)ans;else if(i % 38 0)ans;}cout<<ans<<endl;return 0; } 2. 祝福…

使用Node.js从零搭建DeepSeek本地部署(Express框架、Ollama)

目录 1.安装Node.js和npm2.初始化项目3.安装Ollama4.下载DeepSeek模型5.创建Node.js服务器6.运行服务器7.Web UI对话-Chrome插件-Page Assist 1.安装Node.js和npm 首先确保我们机器上已经安装了Node.js和npm。如果未安装&#xff0c;可以通过以下链接下载并安装适合我们操作系…

deepseek 3FS编译

3FS在ubuntu22.04下的编译&#xff08;记录下编译过程&#xff0c;方便后续使用&#xff09; 环境信息 OS ubuntu 22.04内核版本 6.8.0-52-genericlibfuse 3.16.1rust 1.75.0FoundationDB 7.1.66meson 1.0.0ninja 1.10.1 libfuse编译 以下建议均在root下执行 pip3 install…

每日一练之移除链表元素

题目&#xff1a; 画图解析&#xff1a; 方法&#xff1a;双指针 解答代码&#xff08;注&#xff1a;解答代码带解析&#xff09;&#xff1a; //题目给的结构体 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* }…

力大砖飞,纯暴力搜索——蓝桥p2110(写着玩的)

#include<bits/stdc.h>const int N1000000;using namespace std;bool mp[2][N];int cnt0; int n;void dfs(int row,int col){cntcnt%1000000007;if(coln && row2){cnt;return ;}if(row>2){ //下一列 dfs(0,col1);return;}if(mp[row][col]1){ //下一行 dfs(row…

如何计算两个向量的余弦相似度

参考笔记&#xff1a; https://zhuanlan.zhihu.com/p/677639498 日常学习之&#xff1a;如何计算两个向量或者矩阵的余弦相似度-CSDN博客 1.余弦相似度定理 百度的解释&#xff1a;余弦相似度&#xff0c;又称为余弦相似性&#xff0c;是通过计算两个向量的夹角余弦值来评估…

OkHttp:工作原理 拦截器链深度解析

目录 一、OKHttp 的基本使用 1. 添加依赖 2. 发起 HTTP 请求 3. 拦截器&#xff08;Interceptor&#xff09; 4. 高级配置 二、OKHttp 核心原理 1. 责任链模式&#xff08;Interceptor Chain&#xff09; 2. 连接池&#xff08;ConnectionPool&#xff09; 3. 请求调度…

python: DDD+ORM using oracle 21c

sql script: create table GEOVINDU.School --創建表 ( SchoolId char(5) NOT NULL, -- SchoolName nvarchar2(500) NOT NULL, SchoolTelNo varchar(8) NULL, PRIMARY KEY (SchoolId) --#主鍵 );create table GEOVINDU.Teacher ( TeacherId char(5) NOT NULL , TeacherFirstNa…

基于 LeNet 网络的 MNIST 数据集图像分类

1.LeNet的原始实验数据集MNIST 名称&#xff1a;MNIST手写数字数据集 数据类型&#xff1a;灰度图 &#xff08;一通道&#xff09; 图像大小&#xff1a;28*28 类别数&#xff1a;10类&#xff08;数字0-9&#xff09; 1.通过torchvision.datasets.MNIST下载并保存到本地…

Day4 C语言与画面显示练习

文章目录 1. harib01a例程2. harib01b例程3. harib01e例程4. harib01f例程5. harib01h例程 1. harib01a例程 上一章主要是将画面搞成黑屏&#xff0c;如果期望做点什么图案&#xff0c;只需要再VRAM里写点什么就好了&#xff0c;使用nask汇编语言实现一个函数write_mem8&#…

一周热点-OpenAI 推出了 GPT-4.5,这可能是其最后一个非推理模型

在人工智能领域,大型语言模型一直是研究的热点。OpenAI 的 GPT 系列模型在自然语言处理方面取得了显著成就。GPT-4.5 是 OpenAI 在这一领域的又一力作,它在多个方面进行了升级和优化。 1 新模型的出现 GPT-4.5 目前作为研究预览版发布。与 OpenAI 最近的 o1 和 o3 模型不同,…

《UE5_C++多人TPS完整教程》学习笔记34 ——《P35 网络角色(Network Role)》

本文为B站系列教学视频 《UE5_C多人TPS完整教程》 —— 《P35 网络角色&#xff08;Network Role&#xff09;》 的学习笔记&#xff0c;该系列教学视频为计算机工程师、程序员、游戏开发者、作家&#xff08;Engineer, Programmer, Game Developer, Author&#xff09; Stephe…

手写简易Tomcat核心实现:深入理解Servlet容器原理

目录 一、Tomcat概况 1. tomcat全局图 2.项目结构概览 二、实现步骤详解 2.1 基础工具包&#xff08;com.qcby.util&#xff09; 2.1.1 ResponseUtil&#xff1a;HTTP响应生成工具 2.1.2 SearchClassUtil&#xff1a;类扫描工具 2.1.3 WebServlet&#xff1a;自定义注解…

mac本地安装运行Redis-单机

记录一下我以前用的连接服务器的跨平台SSH客户端。 因为还要准备毕设...... 服务器又过期了&#xff0c;只能把redis安装下载到本地了。 目录 1.github下载Redis 2.安装homebrew 3.更新GCC 4.自行安装Redis 5.通过 Homebrew 安装 Redis 安装地址&#xff1a;https://git…

【ThreeJS Basics 09】Debug

文章目录 简介从 dat.GUI 到 lil-gui例子安装 lil-gui 并实例化不同类型的调整改变位置针对非属性的调整复选框颜色 功能/按钮调整几何形状文件夹调整 GUI宽度标题关闭文件夹隐藏按键切换 结论 简介 每一个创意项目的一个基本方面是能够轻松调整。开发人员和参与项目的其他参与…

【笔记】STM32L4系列使用RT-Thread Studio电源管理组件(PM框架)实现低功耗

硬件平台&#xff1a;STM32L431RCT6 RT-Thread版本&#xff1a;4.1.0 目录 一.新建工程 二.配置工程 ​编辑 三.移植pm驱动 四.配置cubeMX 五.修改驱动文件&#xff0c;干掉报错 六.增加用户低功耗逻辑 1.设置唤醒方式 2.设置睡眠时以及唤醒后动作 ​编辑 3.增加测试命…

类和对象:

1. 类的定义&#xff1a; 1. 类定义格式&#xff1a; 对于我们的类的话&#xff0c;我们是把类看成一个整体&#xff0c;我们的函数里面没有找到我们的成员变量&#xff0c;我们就在我们的类里面找。 我们看我们的第二点&#xff1a; 我们的类里面&#xff0c;我们通常会对…

【十三】Golang 通道

&#x1f4a2;欢迎来到张胤尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 通道通道声明初始化缓冲机制无缓冲通道代码示例 带…