数据结构 栈的概念及栈的实现

本文详细介绍了栈的数据结构概念,包括栈的特点、操作方法(如初始化、入栈、出栈、获取栈顶元素等),以及如何使用数组和链表实现动态增长的栈。同时提供了C语言代码示例,展示了栈的完整操作过程。
摘要由CSDN通过智能技术生成

目录

1.栈的概念及结构

2.栈的实现 

2.1  初始化栈

2.2 入栈 

2.3 出栈 

2.4 获取栈顶元素

2.5 获取栈中有效元素个数 

 2.6  检测栈是否为空,如果为空返回非零结果,如果不为空返回0

2.7 销毁栈 

3. 完整代码

test.c

 Stack.h

Stack.c

 


1.栈的概念及结构

栈(后进先出,先进后出)

一种特殊线性表,其只允许在固定的一端进行插入删除元素操作

进行数据插入删除操作的一端 称为栈顶,另一端称为栈底

栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则

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

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

在内存区域中也有一个区域叫做栈 ,它们一个是数据结构,一个是内存区域

 

2.栈的实现 

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

// 下面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈
typedef int STDataType;
#define N 10
typedef struct Stack
{
	STDataType a[N];
	int top; // 栈顶
}ST;

// 支持动态增长的栈
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);
STDataType STTop(ST* pst);

bool STEmpty(ST* pst);
int STSize(ST* pst);

2.1  初始化栈

void STInit(ST* pst)
{
	//断言出现空指针
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;//栈容量
	// 如果top=0,表示top指向栈顶元素的下一个位置
	pst->top = 0;//栈顶

	// 如果top=-1,表示top指向栈顶元素
	//pst->top = -1;
}

在栈实现中top的初始值的选择是最关键的一点,top既可以初始化为0也可以初始化为-1,如果top=0,表示top指向栈顶元素的下一个位置 ,如果top=-1,表示top指向栈顶元素,这里我们top取0,如果top取-1,下面的一些条件也要发生变化

2.2 入栈 

void STPush(ST* pst, STDataType x)
{
	//断言出现空指针
	assert(pst);
	//判断空间大小是否足够,如果不够,则扩容
	if (pst->capacity == pst->top)
	{
		//如果初始空间为0,则赋为4,如果不是则扩容为原来的2倍
		int newcapacity = pst->capacity == 0 ? 4:pst->capacity * 2;
		//将扩容的新空间存起来
		STDataType* tmp = realloc(pst->a, sizeof(newcapacity)*newcapacity);
		//判定新空间是否开辟成功
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		//将开辟的新空间和空间大小赋给a和capacity
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	//赋值
	pst->a[pst->top] = x;
	pst->top++;
}

:数据结构中动态内存开辟非常重要,如果感觉不太熟悉的话可以看看我之前的文章(感谢支持!)C语言:动态内存管理-CSDN博客

2.3 出栈 

void STPop(ST* pst)
{
	断言出现空指针
	assert(pst);
	//这里top指向栈顶的下一个元素,top减一,看似没有删除元素,实则top已经指向要删除元素的下一个,要删除的元素变成了无效元素,从而达到删除的目的
	pst->top--;
}

这里top指向栈顶的下一个元素,top减一,看似没有删除元素,实则top已经指向要删除元素的下一个要删除的元素变成了无效元素,从而达到删除的目的,这种思想以后我们在数据结构中会经常遇到 。

2.4 获取栈顶元素

STDataType STTop(ST* pst)
{
	//断言出现空指针
	assert(pst);
	return pst->a[pst->top - 1];
}

2.5 获取栈中有效元素个数 

int STSize(ST* pst)
{
	//断言出现空指针
	assert(pst);
	return pst->top;
}

 2.6  检测栈是否为空,如果为空返回非零结果,如果不为空返回0

bool STEmpty(ST* pst)
{
	//断言出现空指针
	assert(pst);
	return pst->top == 0;
}

2.7 销毁栈 

void STDestroy(ST* pst)
{
	//断言出现空指针
	assert(pst);
	free(pst->a);
	pst->capacity = pst->top = 0;
}

3. 完整代码

test.c

#include"Stack.h"

int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	//printf("%d ", STTop(&s));
	//STPop(&s);
	//printf("%d ", STTop(&s));
	//STPop(&s);

	STPush(&s, 4);
	STPush(&s, 5);

	//    一     对     多
	// 入栈顺序  --  出栈顺序
	while (!STEmpty(&s))
	{
		printf("%d ", STTop(&s));
		STPop(&s);
	}
	printf("\n");

	return 0;
}

 Stack.h

#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);
STDataType STTop(ST* pst);

bool STEmpty(ST* pst);
int STSize(ST* pst);

Stack.c

#include "Stack.h"


void STInit(ST* pst)
{
	//断言出现空指针
	assert(pst);
	pst->a = NULL;
	pst->capacity = 0;//栈容量
	// 如果top=0,表示top指向栈顶元素的下一个位置
	pst->top = 0;//栈顶

	// 如果top=-1,表示top指向栈顶元素
	//pst->top = -1;
}
void STDestroy(ST* pst)
{
	//断言出现空指针
	assert(pst);
	free(pst->a);
	pst->capacity = pst->top = 0;
}

// 栈顶插入删除
void STPush(ST* pst, STDataType x)
{
	//断言出现空指针
	assert(pst);
	//判断空间大小是否足够,如果不够,则扩容
	if (pst->capacity == pst->top)
	{
		//如果初始空间为0,则赋为4,如果不是则扩容为原来的2倍
		int newcapacity = pst->capacity == 0 ? 4:pst->capacity * 2;
		//将扩容的新空间存起来
		STDataType* tmp = realloc(pst->a, sizeof(newcapacity)*newcapacity);
		//判定新空间是否开辟成功
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		//将开辟的新空间和空间大小赋给a和capacity
		pst->a = tmp;
		pst->capacity = newcapacity;
	}
	//赋值
	pst->a[pst->top] = x;
	pst->top++;
}
void STPop(ST* pst)
{
	//断言出现空指针
	assert(pst);
	//这里top指向栈顶的下一个元素,top减一,看似没有删除元素,实则top已经指向要删除元素的下一个,要删除的元素变成了无效元素,从而达到删除的目的
	pst->top--;
}
STDataType STTop(ST* pst)
{
	//断言出现空指针
	assert(pst);
	return pst->a[pst->top - 1];
}

bool STEmpty(ST* pst)
{
	//断言出现空指针
	assert(pst);
	return pst->top == 0;
}
int STSize(ST* pst)
{
	//断言出现空指针
	assert(pst);
	return pst->top;
}

感谢观看,希望能对你有所帮助 !

 

  • 27
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

饿了我会自己捡代码吃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值