数据结构之栈详解

news2024/9/23 21:21:27

1. 栈的概念以及结构

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

压栈:栈的插入操作叫做进栈/插栈/入栈,入数据在栈顶。

出栈:栈的删除操作叫做出栈。出数据也在栈顶。

2.栈的功能以及实现

栈的实现一般可以使用数组或者链表来实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小

这里定长的静态栈的结构,实现中一般不实用

//静态栈
typedef int STDataType;

#define N 10
typedef struct Stack
{
    STDataType a[N];
    int top;
}Stack; 

所以我们主要实现下面的支持动态增长的栈

//支持动态增长的栈
typedef int STDataType;

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

栈所需要实现的一些功能

//栈初始化
void STInit(ST* ps);
//清空栈
void STDestroy(ST* ps);

//插入栈
void STPush(ST* ps);
//删除栈元素
void STPop(ST* ps);
//查看栈的大小
int STSize(ST* ps);
//查看栈中有没有元素
bool STEmpty(ST* ps);
//输出栈顶元素
STDataType STTop(ST* ps);

->1. 栈初始化

void STInit(ST* ps)
{
	assert(ps);

	ps->a = (ST*)malloc(sizeof(ST) * CAPACITY__SIZE);
	if (NULL == ps->a)
	{
		perror("STInit::malloc");
		return;
	}

	//压栈元素的下一个位置
	ps->top = 0;
	ps->capacity = CAPACITY__SIZE;
}

->2. 清空栈

//清空栈
void STDestroy(ST* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

->3. 插入栈

//插入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		ST* Expand = (ST*)realloc(ps->a,sizeof(ST) * ps->capacity * CAPACITY__SIZE);
		if (NULL == Expand)
		{
			perror("STPop::malloc");
			exit(-1);
		}

		ps->a = Expand;
		ps->capacity *= CAPACITY__SIZE;
	}

	ps->a[ps->top++] = x;
}

->4. 删除栈元素

//删除栈元素
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty);

	ps->top--;
}

->5. 查看栈的大小

//查看栈的大小
int STSize(ST* ps)
{
	return ps->top;
}

->6. 查看栈中有没有元素

//查看栈中有没有元素
bool STEmpty(ST* ps)
{
	return  ps->top == 0;
}

->7.输出栈顶元素

//输出栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty);

	return ps->a[ps->top - 1];
}

整合以上我们来实现栈,下面是实现栈的完整代码

Stack.h

#define _CRT_SECURE_NO_WARNINGS 1 
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

//动态栈
#define CAPACITY__SIZE 4
typedef int STDataType;

typedef struct Stack
{
	int* a;
	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);

Stack.c

#include "Stack.h"

void STInit(ST* ps)
{
	assert(ps);
	ps->a = (STDataType*)malloc(sizeof(STDataType) * CAPACITY__SIZE);
	if (NULL == ps->a)
	{
		perror("STInit::malloc");
		return;
	}

	//压栈元素的下一个位置
	ps->top = 0;
	ps->capacity = CAPACITY__SIZE;
}

//清空栈
void STDestroy(ST* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->top = 0;
	ps->capacity = 0;
}

//插入栈
void STPush(ST* ps, STDataType x)
{
	assert(ps);

	if (ps->top == ps->capacity)
	{
		STDataType* Expand = (STDataType*)realloc(ps->a,sizeof(STDataType) * ps->capacity * CAPACITY__SIZE);
		if (NULL == Expand)
		{
			perror("STPop::malloc");
			exit(-1);
		}

		ps->a = Expand;
		ps->capacity *= CAPACITY__SIZE;
	}

	ps->a[ps->top++] = x;
}

//删除栈元素
void STPop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	ps->top--;
}
//查看栈的大小
int STSize(ST* ps)
{
	return ps->top;
}

//查看栈中有没有元素
bool STEmpty(ST* ps)
{
	return  ps->top == 0;
}

//输出栈顶元素
STDataType STTop(ST* ps)
{
	assert(ps);
	assert(!STEmpty(ps));

	return ps->a[ps->top - 1];
}

test.c

#include "Stack.h"

int main()
{
	ST Stack;
	STInit(&Stack);
	STPush(&Stack, 1);
	STPush(&Stack, 2);
	STPush(&Stack, 3);
	STPush(&Stack, 4);
	STPush(&Stack, 5);
	/*while (!STEmpty(&Stack))
	{
		printf("%d->", Stack.a[--Stack.top]);

	}
	printf("NULL\n");*/
	while (!STEmpty(&Stack))
	{
		printf("%d ", STTop(&Stack));
		STPop(&Stack);
	}
	printf("\n");
	STDestroy(&Stack);

	return 0;
}

测试结果:

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

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

相关文章

HDU1032——The 3n + 1 problem,HDU1033——Edge,HDU1034——Candy Sharing Game

目录 HDU1032——The 3n 1 problem 题目描述 运行代码 代码思路 HDU1033——Edge 题目描述 运行代码 代码思路 HDU1034——Candy Sharing Game 题目描述 运行代码 代码思路 HDU1032——The 3n 1 problem 题目描述 Problem - 1032 运行代码 #include <iostr…

H3CNE(路由基础、直连路由与静态路由)

目录 6.1 直连路由 6.2 静态路由理解性实验 6.2.1 配置直连路由 6.2.2 配置静态路由 6.3 路由表的参数与比较 6.3.1 优先级的比较 6.3.2 开销的比较 6.4 路由器中的等价路由、浮动路由、默认路由 6.4.1 等价路由 6.4.2 浮动路由 6.4.3 默认路由(缺省路由) 6.1 直连路…

Golang | Leetcode Golang题解之第278题第一个错误的版本

题目&#xff1a; 题解&#xff1a; func firstBadVersion(n int) int {return sort.Search(n, func(version int) bool { return isBadVersion(version) }) }

宿舍生活新升级:智能指纹锁的便捷体验(嘉立创EDA设计)

宿舍生活新升级&#xff1a;智能指纹锁的便捷体验 引言 宿舍生活总是充满挑战和乐趣&#xff0c;但有时也会因为一些小事情而变得复杂。比如&#xff0c;忘记带钥匙或者需要频繁地给室友开门。随着科技的发展&#xff0c;智能设备逐渐走进我们的生活&#xff0c;为日常带来便…

iPhone能运行Windows了 iOS正在被逼加速开放

用iPhone来运行Windows 11&#xff1f;是的&#xff0c;两个八竿子打不着的设备和系统&#xff0c;居然还有融合的一天。虽然不管从哪个方向来看&#xff0c;这都是一个很奇葩的玩法&#xff0c;但是背后却代表着iOS生态的进一步松绑&#xff0c;iOSAndroid化似乎不再仅限于功能…

【iOS】进程与多线程

目录 前言进程和线程进程和线程的区别多线程的意义时间片概念 线程的生命周期线程池的运行策略自旋锁和互斥锁自旋锁互斥锁自旋锁和互斥锁区别原子属性 iOS多线程技术方案 前言 学习此文&#xff1a;iOS多线程 在平时的iOS开发中&#xff0c;多线程是我们常会遇到的&#xff0…

EasyMedia转码rtsp视频流flv格式,hls格式,H5页面播放flv流视频

EasyMedia转码rtsp视频流flv格式&#xff0c;hls格式 H5页面播放flv流视频 文章最后有源码地址 解决海康视频播放视频流&#xff0c;先转码后自定义页面播放flv视频流 先看效果&#xff0c;1&#xff0c;EasyMedia自带的页面&#xff0c;这个页面二次开发改动页面比较麻烦 …

WARNING: The Nouveau kernel driver is currently in use by your system. 处理方法

实践系统&#xff1a; 安装NVIDIA驱动时&#xff0c;提示&#xff1a; WARNING: The Nouveau kernel driver is currently in use by your system. This driver is incompatible with the NVIDIA driver&#xff0c;and must be disabled before proceeding.警告&#xff1…

【分布式锁】Redis实现分布式锁

在分布式系统中&#xff0c;当多个服务实例&#xff08;或节点&#xff09;需要访问或修改同一份共享资源时&#xff0c;就需要使用分布式锁来确保数据的一致性和防止并发问题。这种情况下&#xff0c;传统的Java并发控制机制如ReentrantLock或synchronized就无法满足需求&…

.NET开源、简单、实用的数据库文档生成工具

前言 今天大姚给大家分享一款.NET开源&#xff08;MIT License&#xff09;、免费、简单、实用的数据库文档&#xff08;字典&#xff09;生成工具&#xff0c;该工具支持CHM、Word、Excel、PDF、Html、XML、Markdown等多文档格式的导出&#xff1a;DBCHM。 支持的数据库 Sq…

Docker+consul容器服务的更新与发现

1、Consul概述 &#xff08;1&#xff09;什么是服务注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&#xff0c;也不考虑服务的压力承载&#xff0c;服务之间调用单纯的通过接口访问。直到后来出现了多个节点…

初学MySQl简单sql语句(1)

目录 SQL语句介绍&#xff1a; DDL创建数据库&#xff1a; char和varchar比较 数值类型 数据库存储引擎 数据库存储引擎——InnoDB 数据库存储引擎——MyISAM 数据库存储引擎-MyISAM 和InnoDB区别 修改和删除数据库表 数据库设计三大范式 一、什么是范式 二、约束作…

如何批量重命名文件名?批量快速自定义文件名称怎么操作?

如何批量重命名文件名&#xff1f;批量快速自定义文件名称怎么操作&#xff1f;在高效率的信息化时代&#xff0c;呆板的工作方式已经不能满足我们的时效性&#xff0c;很多场景都需要一个高效率的方法来提升我们的工作效率&#xff0c;来完成任务的进度&#xff01; 如果用手…

redis的持久化机制以及集群模式

1.redis的持久化机制 内存数据库具有高速读写的优势&#xff0c;但由于数据存储在内存中&#xff0c;一旦服务器停止或崩溃&#xff0c;所有数据将会丢失。持久化机制的引入旨在将内存中的数据持久化到磁盘上&#xff0c;从而在服务器重启后能够恢复数据&#xff0c;提供更好的…

Python异常处理机制、调试模式

一、Bug的由来 1、Bug的由来 世界上第一部万用计算机的进化版-马克2号(Mark II) 2、Debug 二、Bug的分类 和 不同异常类型的处理方式 1、粗心导致的语法错误 SyntaxError &#xff08;1&#xff09; # age input(请输入你的年龄) # if age > 18: # print(成年人..…

深入浅出mediasoup—通信框架

libuv 是一个跨平台的异步事件驱动库&#xff0c;用于构建高性能和可扩展的网络应用程序。mediasoup 基于 libuv 构建了包括管道、信号和 socket 在内的一整套通信框架&#xff0c;具有单线程、事件驱动和异步的典型特征&#xff0c;是构建高性能 WebRTC 流媒体服务器的重要基础…

华为AR6300S路由器开启SSH远程登录

登录华为路由器&#xff1a; 使用控制台线连接到路由器的控制台端口或者通过Telnet或Web界面远程登录到设备。进入系统视图&#xff1a; 输入system-view&#xff08;或者简写为sys&#xff09;命令进入系统视图模式&#xff0c;这是配置全局参数的地方。生成RSA密钥对&#x…

dockerfile部署wordpress

1.将容器直接提交成镜像 [rootlocalhost ~]# docker commit 8ecc7f6b9c12 nginx:1.1 sha256:9a2bb94ba6d8d952527df616febf3fbc8f842b3b9e28b7011b50c743cd7b233b [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE nginx …

昇思25天学习打卡营第22天 | DCGAN生成漫画头像

昇思25天学习打卡营第22天 | DCGAN生成漫画头像 文章目录 昇思25天学习打卡营第22天 | DCGAN生成漫画头像DCGAN模型数据集数据下载和超参数创建数据集数据集可视化 搭建网络生成器判别器损失函数和优化器 模型训练总结打卡 DCGAN模型 深度卷积对抗生成网络&#xff08;Depp Co…

【区块链+绿色低碳】巴中市生态价值核算创新应用 | FISCO BCOS应用案例

生态产品总值&#xff08;GEP&#xff09;&#xff0c;指一定区域生态系统为人类福祉和经济社会可持续发展提供的产品与服务价值总和&#xff0c;包 括供给产品价值、调节服务价值和文化服务价值。当前&#xff0c;推动生态产品价值有效转化存在“难度量、难抵押、难交易、 难变…