史上最强数据结构----轻松拿捏栈的两种模拟实现

本文介绍了栈这种特殊线性表的基本概念与结构特点,并详细探讨了两种主要的栈实现方式:数组栈与链表栈。文章提供了完整的C语言实现代码,帮助读者深入理解栈的工作原理及其实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 栈的概念及结构

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

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

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

image-20220325202945680

注意:数据结构中的栈和我们C语言中的栈有什么关系吗?

前者是一种数据结构,用来存储数据。后者是操作系统中内存划分的一个区域,叫做栈,用来函数调用时,建立栈帧。

问:当入栈顺序是1 2 3 4的时候,出栈顺序一定是4 3 2 1吗?

答:不一定是,因为有可能是1入栈之后接着就出栈了,2、3、4也同样如此,此时的出栈顺序是1 2 3 4。实际上是有很多种出栈方式,后进先出是相对的。

2. 栈的实现

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

image-20220325195054807

栈的代码实现:

2.1 数组栈的实现

第一种:数组栈的实现(推荐)

image-20220326154549746

Stack.h文件代码:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{
	STDataType* a;
	int top;//栈顶的位置
	int capacity;//容量
}ST;
void StackInit(ST*ps);
void StackDestory(ST* ps);
void StackPush(ST* ps,STDataType x);
void StackPop(ST* ps);
bool StackEmpty(ST* ps);
int SizeStack(ST* ps);
STDataType StackTop(ST* ps);

Stack.c文件代码:

#include"Stack.h"
void StackInit(ST* ps)//栈的初始化
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = 0;
	ps->top = 0;
}
void StackDestory(ST*ps)//栈的销毁
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity =ps->top =  0;
}
void StackPush(ST* ps, STDataType x)
{
	assert(ps);
	if (ps->top == ps->capacity)//满了进行扩容
	{
		int newCapacity = ps->capacity == 0 ? 2 : 2 * ps->capacity;
		STDataType*new = (STDataType*)realloc(ps->a,sizeof(STDataType)*newCapacity);
		if (new == NULL)
		{
			printf("fail malloc\n");
			exit(-1);
		}
		ps->a = new;
		ps->capacity = newCapacity;
	}
	ps->a[ps->top++] = x;
}
void StackPop(ST* ps)//出栈
{
	assert(ps);
	assert(ps->top > 0);
	--ps->top;
}
bool StackEmpty(ST* ps)//判断栈是否为空
{
	assert(ps);
	return ps->top == 0;
}
STDataType StackTop(ST* ps)//取栈顶元素
{
	assert(ps);
	assert(ps->top > 0);

	return ps->a[ps->top - 1];
}
int SizeStack(ST* ps)//求栈的元素数量
{
	assert(ps);
	return ps->top;
}

2.2 链表栈的实现

第二种:链表栈的实现
image-20220329124520653

链表栈的实现在此处是运用了单链表(有哨兵位)作为载体,入栈的位置采取的是单链表的头部,即哨兵位的后面的位置,出栈出的也是哨兵位后面的节点。

Stack.h文件代码:

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct StackNode
{
	STDataType val;
	struct StackNode* next;
}StackNode;
StackNode* StackInit();
void StackDestory(StackNode* ps);
void StackPush(StackNode* ps,STDataType x);
void StackPop(StackNode* ps);
bool StackEmpty(StackNode* ps);
int SizeStack(StackNode* ps);
STDataType StackTop(StackNode* ps);
StackNode* BuyStackNode(STDataType x);

Stack.c文件代码:

#include"Stack.h"
StackNode* BuyStackNode(STDataType x)//开辟一个栈(链表的)节点
{
	StackNode* newnode = (StackNode*)malloc(sizeof(StackNode));
	if (newnode == NULL)
	{
		printf("fail malloc\n");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->val = x;
	return newnode;
}
StackNode* StackInit()//栈的初始化
{
	StackNode* head = BuyStackNode(-1);
	return head;
}
void StackDestory(StackNode* ps)//栈的销毁
{
	assert(ps);
	StackNode* cur = ps;
	while (cur)
	{
		StackNode* next = cur->next;
		free(cur);
		cur = next;
	}
}
void StackPush(StackNode* ps, STDataType x)//入栈
{
	assert(ps);
	StackNode* newnode = BuyStackNode(x);
	StackNode* next = ps->next;
	ps->next = newnode;
	newnode->next = next;
}
void StackPop(StackNode* ps)//出栈
{
	assert(ps);
	assert(ps->next);
	StackNode* pop = ps->next;
	ps->next = pop->next;
	free(pop);
}
bool StackEmpty(StackNode* ps)//判断栈是否为空
{
	assert(ps);
	return ps->next == NULL;
}
int SizeStack(StackNode* ps)//求栈中有的节点的数目
{
	assert(ps);
	int size = 0;
	StackNode* cur = ps->next;
	while (cur)
	{
		size++;
		cur = cur->next;
	}
	return size;
}
STDataType StackTop(StackNode* ps)//求栈顶的节点存储的元素
{
	assert(ps);
	assert(ps->next);
	return ps->next->val;
}
### 回答1: 《史上最强-kettle-培训教程.pdf》是一本关于Kettle软件的培训教程,旨在帮助读者了解和掌握Kettle工具的使用。Kettle(Kitchen Extract,Transform,Transport and Load Environment)是一款强大的ETL工具,用于数据仓库建设、数据抽取、转换和加载等工作。 这本培训教程通过详细的步骤和案例介绍了Kettle工具的各个功能和应用场景。首先,它从Kettle的基本介绍开始,包括Kettle的功能特点、安装和环境配置等方面。接着,介绍了Kettle的三个核心模块:抽取(Extract)、转换(Transform)和加载(Load),并通过实际案例演示了如何进行数据抽取、清洗、转换和加载。 此外,该培训教程还介绍了Kettle常用的数据处理技术和工具,如数据清洗、数据合并、数据拆分、数据过滤等,以及Kettle与其他数据库软件(如MySQL、Oracle)的集成方法。同时,还详细介绍了Kettle的作业调度、性能优化、运行监控等高级功能,使读者能够更好地使用Kettle进行大规模数据处理和ETL工作。 总的来说,《史上最强-kettle-培训教程.pdf》是一本全面而实用的Kettle培训教程,无论是初学者还是有一定Kettle使用经验的人都能从中受益。通过学习这本教程,读者能够系统地掌握Kettle的使用方法和技巧,提高数据处理的效率和质量,为企业的数据分析和决策提供有力支持。 ### 回答2: 《史上最强-kettle-培训教程.pdf》是一本介绍数据集成工具Kettle的培训教程。Kettle,全称“Kettle Extraction, Transformation, Loading”,是一款开源的ETL(Extract, Transform, Load)工具,可以帮助用户高效地进行数据集成和数据处理。 这本教程由作者经过精心编写,旨在帮助读者快速掌握Kettle的使用方法和技巧。教程的内容分为多个章节,涵盖了Kettle的基本概念、安装配置、基本操作、数据抽取与转换、数据加载等方面的知识点,旨在帮助读者系统地了解Kettle的功能和应用场景。 教程的特点是内容详尽、通俗易懂。作者在讲解每个知识点时,都采用了简单明了的语言和图例,使得读者能够轻松理解和掌握。此外,教程还提供了实例演示和练习题,帮助读者巩固所学的知识并能够独立运用Kettle进行数据集成和处理。 《史上最强-kettle-培训教程.pdf》毫无疑问是一本对于想要学习和应用Kettle的人来说非常有价值的资料。无论是对于初学者还是有一定经验的用户,都能够从中获得新的知识和技能。通过学习这本教程,读者将能够充分利用Kettle的强大功能,提高工作效率,并能够更好地应对数据集成和处理的需求。 ### 回答3: 《史上最强-kettle-培训教程.pdf》是一本关于使用 Kettle 软件进行培训的教程资料。Kettle 是一款强大的开源的ETL工具,用于数据抽取、转换和加载。这个教程资料以其详细、全面和易懂的内容,被誉为史上最强的培训教程之一。 首先,这本教程在内容上非常丰富,涵盖了Kettle软件的各个方面。无论是初学者还是有一定经验的从业者,都能从中找到适合自己的学习内容。教程按照逻辑顺序,从介绍Kettle的基本概念开始,逐步深入讲解了数据源连接、数据转换、数据处理和数据加载等主要功能。此外,还有许多实际案例和示例,帮助读者更好地理解和应用所学知识。 其次,这本教程的讲解方式简洁明了,语言通俗易懂。即使没有相关的IT专业知识背景,读者也能够轻松理解和掌握Kettle的使用方法。教程中使用了大量的图表、示意图和代码示例,通过直观的形式展示Kettle的操作步骤和实际效果,使学习过程更加直观、生动。 最重要的是,这本教程注重实践的指导,强调学以致用。教程中不仅讲解了理论知识,还提供了许多实践操作的机会,使读者能够通过实际操作来巩固所学的知识。同时,教程还介绍了一些常见的问题和解决方案,帮助读者解决在实际应用中遇到的困难。 总之,《史上最强-kettle-培训教程.pdf》是一本内容丰富、讲解清晰、实践导向的教程资料。无论是初学者还是有经验的用户,都能从中受益匪浅。通过学习这本教程,读者可以更好地掌握Kettle软件的使用,提高数据处理和分析的能力。
评论 102
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鹿九丸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值