【DS】C语言实现栈(动画演示)

用动图详细讲解——栈 用动图详细讲解栈,直观并易理解 阅读详情

栈的介绍

栈的概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫叫做出栈。出数据也在栈顶。

栈的介绍

栈的实现

由栈的定义可知:栈要遵循后进先出LIFO(Last In First Out)的原则。所以在设计实现栈时,用顺序表即数组来实现栈是十分合适的(数组对尾部操作方便)

栈的结构

采用动态数组来实现栈。其结构有一个指向数组的指针,记录栈顶位置的top,检查容量的capacity

typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}ST;

栈的初始化

将所有成员都初始化置为0。要改变Stack这个结构体就要将其地址传过来,所以用assert断言一下,防止传错。

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

插入数据——入栈

入栈动图
数据入栈就要检查空间是否足够,采用realloc以二倍的速度来动态扩容。
在确定空间足够的情况下,将数据插入数组即可

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)//检查剩余容量
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		ST* tmp = (ST*)realloc(pst->a, sizeof(STDataType ) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc failed");
			return;
		}
		pst->capacity = newcapacity;
		pst->a = tmp;
		tmp = NULL;
	}
	pst->a[pst->top++] = x;
}

需要注意malloc开辟的是数组a的空间,而不是开辟栈的空间
注意扩容后要将capacity更新。
插入数据后要将栈顶位置上移即top++

删除数据——出栈

出栈动图演示
数据出栈要检查是否还有数据,随后将栈顶位置top–完成出栈,无需对原有数据进行修改,因为当有新数据再次入栈时就会覆盖原有数据

void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->a[pst->top--];
}

获取栈的元素个数

top即是栈顶位置也是元素个数,返回就好了

int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

获取栈的元素

要注意top是栈顶位置,需要减一来访问栈顶元素

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}

判断栈是否为空

该函数返回值为布尔类型,该类型变量取值为true或false。
一般通过assert来检查是否为空(assert(!STEmpty(pst));)。当STEmpty返回值为假时,说明还有数据,!STEmpty(pst)即为真,不会引起断言。当STEmpty返回值为真时,说明没有数据了,!STEmpty(pst)即为假,引起断言

bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}

assert断言的是假。这一段可能有点绕,如果不清晰还需多看几遍

栈的销毁

栈的销毁也十分简单,只需要把realloc在堆区开辟的空间free掉,并将全部置为0即可。
栈的数据打印也与以往有些不同,具体在下面完整代码的test文件中

void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

完整代码

按我的习惯依旧分成了三个文件
Stack.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDataType;

typedef struct Stack
{
	STDataType* a;
	int top;//栈顶
	int capacity;//容量
}ST;

void STInit(ST* pst);//初始化
void STDestroy(ST* pst);//销毁
void STPush(ST* pst, STDataType x);//入栈
void STPop(ST* pst);//出栈
int STSize(ST* pst);//获取元素个数
STDataType STTop(ST* pst);//获取栈顶元素
bool STEmpty(ST* pst);//判空

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1 
#include"Stack.h"

void STInit(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

void STDestroy(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

void STPush(ST* pst, STDataType x)
{
	assert(pst);
	if (pst->capacity == pst->top)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		ST* tmp = (ST*)realloc(pst->a, sizeof(STDataType ) * newcapacity);
		if (tmp == NULL)
		{
			perror("realloc failed");
			return;
		}
		pst->capacity = newcapacity;
		pst->a = tmp;
		tmp = NULL;
	}
	pst->a[pst->top++] = x;
}

void STPop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	pst->a[pst->top--];
}

int STSize(ST* pst)
{
	assert(pst);
	return pst->top;
}

STDataType STTop(ST* pst)
{
	assert(pst);
	assert(!STEmpty(pst));
	return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1 
#include"Stack.h"

void STTest()
{
	ST st;
	STInit(&st);
	/*STPush(&st, 1);
	STPush(&st, 2);
	STPop(&st);
	STPush(&st, 3);
	STPush(&st, 4);
	printf("Size:%d\n", STSize(&st));
	printf("Top:%d\n", STTop(&st));
	
	while (!STEmpty(&st))//栈的数据打印
	{
		STDataType top = STTop(&st);
		STPop(&st);
		printf("%d ", top);
	}*/

	STDestroy(&st);
}

int main()
{
	STTest();

	return 0;
}
C语言利用双向栈的操作实现两个栈共享一段空间并且分别存放奇偶数 C语言利用双向栈的操作实现两个栈共享一段空间并且分别存放奇偶数 题目均在sdibt acm oj上AC,参考《深入浅出数据结构和算法》教材,逐个复制即可运行,欢迎评论指正! Description 两个栈共享一段存储空间,栈1自左向右增长,栈2自右向左增长,双向栈的存储结构如下: # define MAXSIZE 10 typedef struct {   ElemType data[M... 阅读详情

相关推荐

虚拟机实现(C语言)

reference: https://felixangell.com/blog/implementing-a-virtual-machine-in-c/ 介绍 这里写篇文章介绍一下用C语言实现虚拟机。我喜欢从事底层程序的工作, 比如编译器、解释器、解析器和虚拟机等。所以我写这篇文章来学习一下虚拟机是如何工作的,以此来带领自己进入底层编程领域。 前提 继续这篇文章之前你需要有: GCC/Cla...

bdss58的专栏 1万+

数据结构——栈(Stack)(GIF图解)

一、栈的定义 栈是限定仅在表尾进行插入和删除操作的线性表. 二、 栈的特点 栈也是一种线性结构; 相比数组,栈所对应的操作是数组的子集; 栈只能从一端添加元素,也只能从这一端取出元素,这一端通常称之为"栈顶"; 向栈中添加元素的过程,称之为"入栈",从栈中取出元素的过程称之为"出栈"; 栈的描述如下图: 三、栈的实现 ...

weixin_43294413的博客 5737

ds12c887程序C语言,时钟芯片DS12C887使用说明详解.doc

汇编程序:ORG 0000HAJMP STARTSTART:ACALL SETTIME;设置初始时间LOOP: ACALL GETTIME;循环读取当前时间AJMP LOOP;SETTIME:MOV DPTR,#7D0AH;DS12C887的A寄存器MOV A,#20HMOVX @DPTR,A;打开DS12C887的内部晶振并使RTC(实时时钟)记录时间INC DPTR;DS12C887的B寄...

weixin_29012765的博客 1586

Stack详解(含动画演示)

上面我们自己利用Object 数组和Arrays.copyOf方法实现了简单的栈,我们默认设置了10的容量,如果超过10个元素,我们利用Arrays.copyOf完成数组的复制。我们利用Object 数组和Arrays.copyOf方法实现了一个简单的栈,这个栈包含基本的 push、peek、pop、size、isEmpty方法,并模拟出栈顺序重写了 toString。Stack通过操作数组的末尾,比如push只把元素添加到数组的末尾,pop只移除数组末尾的元素。它直接访问 Vector 的最后一个元素。

落日的博客 1626

栈与递归的动画演示(swf)

栈与递归的动画演示 栈与递归的动画演示 栈与递归的动画演示

UE4 - 河流流体插件Fluid Flux

Fluid Flux可以模拟一定区域内的流体效果,由于使用顶视图所Capture的Heightfield信息,所以只支持室外开阔场景,不支持洞穴等室内场景;

GT的虚幻引擎文档 6671

跟着动画学 Go 数据结构之 Go 实现栈#私藏项目实操分享#

什么是栈类似于链表,栈是一种简单的数据结构。在栈中,数据的取值顺序非常重要。栈的生活例子栈也有许多真实生活示例。考虑在食堂中彼此堆叠的板的简单示例。栈有点像洗碟子然后堆碟子,最先洗的一定是最上面的碟子,然后洗干净后,放到碟子的最下面。第一个放好的碟子永远是最后一个被取用的。可以简单地看到它遵循LIFO / FILO 原则。...

宇宙之一粟的技术漂泊之旅 263

WSL基础环境配置方案

通过以上步骤,您已经在 Windows 的 WSL 环境中成功搭建了一个完整的基础开发环境,包含 Docker、Kubernetes、Helm、kubectl、yq、Git 等工具。这套环境特别适用于在国内使用阿里云镜像服务部署和管理 Tekton,提升了开发和运维的效率和稳定性。

落魄书生的职业学习生涯 8876

c语言模拟实现栈(动图演示)

栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶 (top),另一端为栈底 (bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。由定义可知,栈是线性表,所以我们用数组来实现,其次我们知道他是可以获取堆顶元素的,所以我们还需要一个top指针记录栈顶的位置(这个不是真正意义上的指针,而是记录栈顶元素的位置),且因为我们是动态开辟实现栈,所以我们还需要一个capacity来记录当前的元素个数(相当于size),以检查是否需要进行扩容。

sea18323的博客 949

QT触摸屏开发:如何通过重写事件处理实现精准按键长按检测

本文针对QT触摸屏开发中按键长按检测不精准的常见问题,深入剖析了传统信号机制失效的原因,并提供了通过重写事件处理函数(event)的解决方案。文章详细介绍了创建自定义TouchButton类、直接处理QTouchEvent以实现可靠长按检测的完整步骤与代码示例,并分享了进阶优化与避坑指南,帮助开发者实现跨平台一致的精准交互。

weixin_29207149的博客 95

Android手机免root玩转Kali NetHunter:Termux保姆级安装指南(附Kex VNC配置)

本文提供了一份详细的Android手机免root安装Kali NetHunter的保姆级指南。通过使用Termux终端模拟器,用户无需解锁Bootloader或获取root权限,即可在普通安卓设备上部署完整的Kali Linux渗透测试环境。教程涵盖了从环境准备、NetHunter核心安装到配置Kex VNC实现图形桌面访问的全过程,并附带了电脑投屏与常见问题解决方案,旨在打造一个便携的移动安全学习与测试平台。

weixin_29208327的博客 302

DS初阶:栈和队列的相互实现

栈和队列的相互实现是用两个栈去实现队列或者是用两个队列去实现栈,这样其实是把问题复杂化的,实际中没有什么应用价值,但是通过他们的相互实现可以让我们更加深入地理解栈和队列的特点

weixin_51142926的博客 3164

点云处理实操(四) -PCL中的点云三角化

点云处理实操(四) -PCL中的点云三角化

cangqiongxiaoye的博客 939

【DS】C语言实现队列(动画演示)

C语言使用链表完成队列的实现

Mesar的博客 1336

SKUA-GOCAD入门教程-第七节 点的创建与编辑3

本文介绍了四种从井数据创建点集的方法

江洋大葱的博客 963

半导体设备系列(2) 半导体设备与工厂控制仿真器Demo编写

基于C/S架构用C++编写半导体设备仿真器与工厂控制仿真器

追赶时代的博客 610

【DS】C语言实现堆(动画演示)

对二叉树进行简略讲解。详细介绍堆的实现,使用动画演示更便于理解

Mesar的博客 1095

2026年复旦微电数字IC笔试试卷带答案解析

摘要: 本文为复旦微电子MCU/SOC岗位笔试模拟题,涵盖单片机架构、数字电路、存储技术等核心知识点。内容包括: 单选题(30分):考察Cortex-M中断机制、时序分析(建立/保持时间)、逻辑化简、跨时钟域设计(格雷码应用)、存储器特性(NAND Flash操作单元)等; 波形分析(15分):聚焦D触发器行为、时钟分频、建立时间违例判断及跨时钟域同步; 多选题(25分):涉及亚稳态成因与处理、异步FIFO设计要点、MCU低功耗策略、NAND Flash特性及复旦微电市场地位; 简答题(20分):解析建立/

Open 344

【DS】C语言实现堆排序及应用(动画演示)

基于堆实现堆排序及TopK问题,增加对堆的理解

Mesar的博客 1281

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

栈的实现(c语言)

栈作为一种数据结构是遵循先入后出的原则只能在同一端进行输入和输出。而允许进行插入和删除操作的一端称为栈顶,另一端为栈底;栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。栈的插入数据被称为入栈,取出数据则是为出栈。

lixin203171613的博客 2210

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

c语言void ds,ds1307怎么使用(ds1307引脚图及功能_c语言程序及典型应用电路)

描述实时时钟DS1307 介绍:DS1307是低功耗、两线制串行读写接口、日历和时钟数据按BCD码存取的时钟/日历芯片。它提供秒、分、小时、星期、日期、月和年等时钟日历数据。另外它还集成了如下几点功能:(1)56 字节掉电时电池保持的NV SRAM 数据存储器(2)可编程的方波信号输出(3)掉电检测和自动切换电池供电模式DS1307 把8 个寄存器和56 字节的RAM 进行了统一编址,具体地址和寄...

weixin_39917437的博客 1232

DS28E01 加密算法 C语言实现:高效安全的加密解决方案

DS28E01 加密算法 C语言实现:高效安全的加密解决方案 去发现同类优质开源项目:https://gitcode.com/ 项目介绍 在当今数字化时代,数据安全已成为企业和个人关注的焦点。DS28E01加密算法作为一种高效且安全的加密技术,广泛应用于各种需要保护数据完整性和机密性的场景。本项目提供了一个用C语言实现的DS28E01加密算法,并附有详细的实现文档,旨在帮助开发者快速理解和应用这一...

gitblog_09758的博客 1116

DS线性表之栈的讲解和实现(4)

栈就是一个比较实用的数据结构了,且大致逻辑就是套用之前的两种线性表具体选择哪种呢?请看正文!栈是我们学习的第一个实用数据结构,且我们在未来的学习会经常遇到它,请好好体会它“后进先出”的思想,想想可能会有哪些具体实用场景。

tan180°的博客 1026

0c400汇编语言地址,DS80C400的Keil C语言编程.doc

DS80C400的Keil C语言编程摘要:在设计DS80C400网络微控制器的ROM时,一组功能被公开出来,可以在8051汇编、C或Java?程序中访问。DS80C400的ROM可以被视作一个构建C或汇编程序的起跑架,它提供TINI?经过验证的网栈、进程调度器和存储器管理器。简单程序,如网络扬声器,可以用汇编语言轻松实现,更复杂一点的,如HTTP服务器这种需要与文件系统交互的程序,可以使用C语言...

weixin_32281549的博客 208

【DS】栈和队列的实现

栈的代码实现: #include <stdio.h> #include <cstdbool> #include <assert.h> // 栈适合用数组实现,队列不适合找尾,出栈的时候,找尾麻烦。所以数组实现相较于链表更加简单方便。 typedef int STDataType; typedef struct Stack { STDataType* _a...

进阶之路 172

DS28E01 加密算法 C语言实现

DS28E01 加密算法 C语言实现 去发现同类优质开源项目:https://gitcode.com/ 概述 本仓库提供了一个用C语言实现的DS28E01加密算法,并附有详细的实现文档。该代码经过测试,确保其可用性。代码来源于网络,如有侵权,请联系删除。 资源文件内容 DS28E01 加密算法 C语言代码:包含了DS28E01加密算法的完整C语言实现。 详细实现文档:提供了算法实现的详细说明,帮...

gitblog_09710的博客 485
上一篇: 【DS】C语言实现带头双向循环链表(详细图解)
下一篇: 【DS】C语言实现队列(动画演示)
Mesar_
博客等级 码龄3年 926粉丝 56原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值