【数据结构】栈基本操作的实现(C语言)

news2025/7/9 10:24:01

🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。
🐌 个人主页:蜗牛牛啊
🔥 系列专栏:🛹初出茅庐C语言、🛴数据结构
📕 学习格言:博观而约取,厚积而薄发
🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与诸君一同成长! 🌹


文章目录

  • 一、栈的概念
  • 二、栈的实现
    • 1.初始化栈
    • 2.压栈
    • 3.出栈
    • 4.打印栈中元素
    • 5.判断栈是否为空
    • 6.返回栈顶元素
    • 7.统计栈中元素个数
  • 三、测试代码

一、栈的概念

栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底,栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做压栈/入栈/进栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈,出数据也在栈顶。
以1、2、3、4为例的入栈操作和出栈操作演示过程如下所示:

入栈和出栈操作

二、栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些,因为数组在尾上插入数据的代价比较小。用动态数组实现时唯一的缺陷就是需要扩容;也可以使用单链表实现,单链表的头插头删更方便,所以单链表的头可以当作栈顶,单链表的尾可以当作栈底。本篇文章采用的是动态开辟的数组实现对栈的基本操作。

1.初始化栈

void StackInit(ST* ps)//初始化栈
{
	assert(ps);//避免传过来的地址为空
	STDataType* tmp = (STDataType*)malloc(sizeof(STDataType*)*4);
	if (tmp == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	ps->arr = tmp;
	ps->top = 0;
	ps->capacity = 4;
}

初始化栈时必须要断言,避免穿过来的指针为空,同时也避免了当定义变量为ST* st=NULL; 对其进行初识化StackInit(st)这种情况的发生。top初始化为0,表示指向栈顶元素的下一个位置,也可以表示栈中的元素个数;top初始化为-1,表示指向栈顶元素。

2.压栈

void StackPush(ST* ps, STDataType x)//压栈
{
	assert(ps);
	if (ps->capacity == ps->top)
	{
		STDataType* tmp = (STDataType*)realloc(ps->arr, sizeof(STDataType*) * 2 * ps->capacity);
		if (tmp == NULL)
		{
			perror("realloc");
			exit(-1);
		}
		ps->arr = tmp;
		ps->capacity = 2 * ps->capacity;
	}
	ps->arr[ps->top] = x;
	ps->top++;
}

压栈时要检查数组是否已满,是否需要对其进行扩容。

3.出栈

void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(ps->top > 0); //可以使用 assert(!StackEmpty);
	ps->top--;
}

对其进行出栈操作时要判断栈是否为空。

4.打印栈中元素

void StackPrint(ST* ps)//打印栈中元素
{
	int i = 0;
	for (i = 0; i < ps->top; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");
}

5.判断栈是否为空

bool StackEmpty(ST* ps)//判断是否为空
{
	assert(ps);
	if (ps->top == 0)
		return true;
	return false;
	//也可以直接使用return ps->top == 0;
}

6.返回栈顶元素

STDataType StackTop(ST* ps)//返回栈顶元素
{
	assert(ps);
	assert(ps->top > 0);//可以使用 assert(!StackEmpty);
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

初始化时ps->top=0,指向的是栈顶元素的下一个位置,所以返回栈顶元素的时候,要对其进行减操作。

7.统计栈中元素个数

int StackSize(ST* ps)//统计栈中元素个数
{
	assert(ps);
	return ps->top;
}

初始化时ps->top=0,既表示栈顶元素的下一个位置,也可以表示栈中元素个数。

三、测试代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
typedef int STDataType;
typedef struct Stack {
	STDataType* arr;
	int top;
	int capacity;
}ST;
void StackInit(ST* ps)//初始化栈
{
	assert(ps);//避免传过来的地址为空
	STDataType* tmp = (STDataType*)malloc(sizeof(STDataType*) * 4);
	if (tmp == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	ps->arr = tmp;
	ps->top = 0;
	ps->capacity = 4;
}
void StackDestroy(ST* ps)//销毁栈
{
	assert(ps);
	free(ps->arr);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, STDataType x)//压栈
{
	assert(ps);
	if (ps->capacity == ps->top)
	{
		STDataType* tmp = (STDataType*)realloc(ps->arr, sizeof(STDataType*) * 2 * ps->capacity);
		if (tmp == NULL)
		{
			perror("realloc");
			exit(-1);
		}
		ps->arr = tmp;
		ps->capacity = 2 * ps->capacity;
	}
	ps->arr[ps->top] = x;
	ps->top++;
}
void StackPrint(ST* ps)//打印栈中元素
{
	int i = 0;
	for (i = 0; i < ps->top; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");
}
void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(ps->top > 0); //可以使用 assert(!StackEmpty);
	ps->top--;
}
bool StackEmpty(ST* ps)//判断是否为空
{
	assert(ps);
	if (ps->top == 0)
		return true;
	return false;
	//也可以直接使用return ps->top == 0;
}
STDataType StackTop(ST* ps)//返回栈顶元素
{
	assert(ps);
	assert(ps->top > 0);//可以使用 assert(!StackEmpty);
	assert(!StackEmpty(ps));
	return ps->arr[ps->top - 1];
}

int StackSize(ST* ps)//统计栈中元素个数
{
	assert(ps);
	return ps->top;
}
void TestStack()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);
	StackPush(&st, 4);
	StackPush(&st, 5);
	StackPush(&st, 6);
	StackPrint(&st);

	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	StackPop(&st);
	StackPrint(&st);

	if (!StackEmpty(&st))
		printf("栈顶元素:%d\n栈中总的元素个数:%d\n", StackTop(&st),StackSize(&st));

	StackDestroy(&st);
}
int main()
{
	TestStack();
	return 0;
}

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

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

相关文章

SpringBoot项目打包时配置文件区分日常、测试、预发、正式环境

前言&#x1f34a; 在我们开发项目的时候&#xff0c;一般有四套环境&#xff1a;日常、测试、预发、正式。日常环境作为我们开发环境&#xff1b;测试环境给测试同学测试功能&#xff1b;预发环境给正式环境发布时提供准备&#xff1b;正式环境则是稳定的生产环境。 这四套环…

面试官问我new Vue阶段做了什么?

前言 本篇录入吊打面试官专栏&#xff0c;希望能祝君拿下Offer一臂之力&#xff0c;各位看官感兴趣可移步&#x1f6b6;。这段时间面了很多家公司&#xff0c;被问到的题我感觉不重复不止100道&#xff0c;将会挑选觉得常见且有意义的题目进行分析及回答。有人说面试造火箭&am…

Redis字符串、hash、列表方法使用以及Redis管道与Django集成Redis

目录标题一、Redis字符串操作二、Redis-hash操作三、Redis列表操作四、Redis管道五、Redis其他操作六、Django中集成Redis七、Celery介绍一、Redis字符串操作 名称属性setex:过期时间&#xff08;秒&#xff09;px:过期时间(毫秒) nx:如果设置为True&#xff0c;则只有name不存…

毕业设计:SpringBoot+Vue+Element的校内跑腿平台

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 文末获取源码 项目编号&#xff1a;BS-XX-…

MySQL基础总结

一.sql数据及语言基本类型: 1.语言的分类 DDL:数据定义语言,用来定义数据库对象:数据库,表,列等。关键字:create,alter,drop等 DML:数据操作语言,用来对数据库中表的记录进行操作。关键字:insert,delete,update等 DQL:数据库查询语言,用来查询数据库中表的记录。关键字:select,…

PIX2SEQ: A LANGUAGE MODELING FRAMEWORK FOR OBJECT DETECTION

文章目录ABSTRACT1 INTRODUCTION2 pix2seq框架2.1SEQUENCE CONSTRUCTION FROM OBJECT DESCRIPTIONS2.2 ARCHITECTURE, OBJECTIVE AND INFERENCE2.3 SEQUENCE AUGMENTATION TO INTEGRATE TASK PRIORS3 EXPERIMENTS3.1 EXPERIMENTAL SETUP3.2 MAIN COMPARISONS3.3 ABLATION ON SE…

2022年都在说软件测试饱和了?都在担心面试不上。

今年开始&#xff0c;小编听到最多的问题就是 软件测试行业是不是饱和了&#xff1f; 软件测试行业还有前景吗&#xff1f; 无非是因为投出去的简历回复的越来越少了 据中华英才网统计&#xff0c;目前软件测试人才的缺口在100万人以上&#xff0c;并以每年20%的速度递增&am…

2.5 自定义srv C++

功能介绍 以自定义数据类型为基础&#xff0c;完成一个节点作为服务器&#xff0c;另一个节点接收传送两个数字到服务端&#xff0c;服务端计算后反馈到客户端进行打印输出 1、工作空间 1.1 创建工作空间lee_ws mkdir -p ~/lee_ws/src cd ~/lee_ws/src/ catkin_init_worksp…

Unity 旋转大总结和项目操作

操作演示 旋转 (online-video-cutter.com)旋转方法都放在了按钮上&#xff0c;第一个是初始化按钮&#xff0c;将cube恢复到&#xff08;0&#xff0c;0&#xff0c;0&#xff09;&#xff0c;但是位置不会变成&#xff08;0&#xff0c;0&#xff0c;0&#xff09; 这个是参…

clickhouse中的sql操作

DDL操作 create操作 create table t_order_mt2(id UInt32,sku_id String,total_amount Decimal(16,2),create_time Datetime,INDEX a total_amount TYPE minmax GRANULARITY 5 ) engine MergeTree partition by toYYYYMMDD(create_time) order by (id, sku_id) primary key …

【工具】工具小集

Gif录制工具 LICEcap一款轻量级屏幕录制工具&#xff0c;可以导出GIF动画图片格式&#xff0c;支持导出GIF 动画图片格式&#xff0c;可灵活调整录制窗口大小。 https://www.cockos.com/licecap/ 浏览器插件&#xff08;工具箱&#xff09; FeHelper插件支持Chrome、Firefox…

创建个人中心页面(下)

目录 布局规划前端页面 获取头像获取Bot列表 对接获取Bot信息渲染到前端 实现创建一个Bot 前端进行对接插入Bot 实现创建成功关闭和清空 修改时间 实现删除按钮 安装依赖&#xff1a;vue3-ace-editor 布局规划前端页面 使用 bootstrap 的 grids system 进行布局 在 bo…

windows常见的命令操作大全

目录 一、目录文件操作 cd命令 dir命令 md命令 rd命令 move命令 copy命令 del命令 二、文本相关操作 type命令 >命令 findstr命令 |命令 三、网络相关操作 小建议&#xff1a;跟着文章亲手敲一遍是避免忘记的有效方法 一、目录文件操作 cd命令 功能&#xf…

你真的会解决android ANR 问题吗?

前言 ​ 还记得之前写过一篇关于ANR 的介绍&#xff0c;现在看来&#xff0c;那个只是皮毛。现实中遇到应用或系统ANR 的问题&#xff0c;是很难解决的。下面进入正题&#xff0c;来详细了解下如何解决。 一.ANR 关键字 1. event log 中“am_ANR” 关键字&#xff0c;main-l…

27岁Python程序员做独立开发年收入超900万,家中有屋又有田,生活乐无边

他是谁 他叫赖利蔡斯&#xff0c;27岁的Python程序员。现在拥有一家自己的小型软件公司。 他现在的生活 躺赚 每天躺着就可以赚到钱&#xff0c;睡觉时从来不会被闹钟吵醒。 每天干自己的喜欢的事情&#xff0c;读书、编程、讨论公司业务、研究自己感兴趣的事情&#xff0…

Java#4(各类语句和一点小练习)

目录 一.分支语句 1.if语句:和C语言中的没有什么区别 2.switch语句:可以使用C语言的写法,但新增了一种更加简便的写法 二. 循环语句 1.for循环:和C语言没有什么太大区别 2.while循环:和C语言没有什么太大区别 练习:回文数的判断 3.do while(先运行一次再判断):和C语言没…

项目经理如何进行项目汇报才能让项目顺利进行,让领导一看就喜欢?

项目经理如何进行项目工作汇报才能让项目顺利进行&#xff0c;让领导一看就喜欢&#xff1f;领导听工作汇报&#xff0c;就是想知道项目干得怎么样。因此&#xff0c;项目经理事先一定要思考&#xff0c;这次工作汇报应该达到什么目的。 工作汇报要注意这三个问题 简单描述项目…

有关Git(小白一看就懂)入门版

git的使用是在工作中必备的技能&#xff0c;本系列重写自己曾经学习git的过程&#xff0c;按照从创建git仓库开始操作&#xff0c;赋每一步的演示图&#xff0c;让小白跟着文章操作&#xff0c;一步一步入门 目录 git基本概念 git使用基本流程 文件的四种状态 git的使用和基…

Vue3 - this 概念及使用方法(详细教程)

前言 对比 Vue2 &#xff0c;引出并展开 Vue3 。 本文讲述了 this 概念及应用场景&#xff0c;以及使用方法和代码示例详细讲解。 回忆 Vue2 我们在 Vue2 项目中&#xff0c;可能写得最多的单词就是 this 了&#xff0c;咱们无论是拿数据还是调方法&#xff0c;一律 this。 先…

前端学习路线(一)

很多人问我前端学习的路线是怎么样的&#xff0c;css要学多久&#xff0c;js高级要不要学&#xff0c;先学node.js还是先学vue&#xff0c;所以想通过一篇博文来讲一下这个事情 要不要学前端三剑客 这个问题是很多想快速上手前端的同学问的最多的一个问题&#xff0c;因为有很…