【数据结构】实现栈

大家好,我是苏貝,本篇博客带大家了解栈,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️


目录

一 .栈的概念及结构

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


二 .栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些,因为数组在尾上插入数据的代价比较小(数组的尾插、尾删很方便)。所以下面我们用数组来实现

1

栈的结构体

c 复制代码
typedef int STDataType;
#define N 10
typedef struct Stack
{
 STDataType _a[N];
 int top; // 栈顶
}ST;

上面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈

c 复制代码
typedef int STDataType;

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

2

初始化

因为我们要对ST类型的变量进行初始化,所以实参要传ST类型变量的地址,用一级指针来接收。因为实参(ST类型变量的地址)不可能为NULL,所以对它断言(下面的接口同理)。

注意:我们这里的top指的是栈顶元素的下一个,而非栈顶元素,所以将它初始化为0

c 复制代码
void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;//指向栈顶元素的下一个
}

3

销毁

注意:在这里我们使用的是动态开辟内存,所以要在销毁时释放掉动态开辟的内存,也就是pst->a指向的那个数组

c 复制代码
void STDestroy(ST* pst)
{
	assert(pst);

	if (pst->a != NULL)
	{
		free(pst->a);
		pst->a = NULL;
		pst->capacity = 0;
		pst->top = 0;
	}
}

4

栈顶插入

再插入元素之前我们要先判断是否要增容,因为在初始化时我们将pst->capacity初始化为0,所以在增容时要特别注意将pst->capacity==0的情况。还要注意对realloc的结果进行判断,防止realloc失败返回NULL,又直接将NULL赋值给pst->a,这样就再找不到开辟的数组了。

最后不要忘记pst->top++

c 复制代码
void STPush(ST* pst, STDataType x)
{
	assert(pst);

	//判断是否需要增容
	if (pst->top == pst->capacity)
	{
		int newcapacity = (pst->capacity == 0) ? 4 : 2 * pst->capacity;
		ST* tmp = (ST*)realloc(pst->a, newcapacity * sizeof(ST));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}

	//插入数据
	pst->a[pst->top] = x;
	pst->top++;
}

5

栈顶删除

删除时我们必须保证栈内有元素,所以要对pst->top>0断言,如果top==0,表示栈内已无元素,返回错误信息,下面的显示栈顶元素同理

c 复制代码
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

6

显示栈顶元素

c 复制代码
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

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

7

是否为空

c 复制代码
bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

8

栈的大小

c 复制代码
int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

三. 模块化代码实现

Stack.h

c 复制代码
#include<stdio.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

c 复制代码
#include"Stack.h"

//初始化
void STInit(ST* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->capacity = 0;
	pst->top = 0;//指向栈顶元素的下一个
}

//销毁
void STDestroy(ST* pst)
{
	assert(pst);

	if (pst->a != NULL)
	{
		free(pst->a);
		pst->a = NULL;
		pst->capacity = 0;
		pst->top = 0;
	}
}

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

	//判断是否需要增容
	if (pst->top == pst->capacity)
	{
		int newcapacity = (pst->capacity == 0) ? 4 : 2 * pst->capacity;
		ST* tmp = (ST*)realloc(pst->a, newcapacity * sizeof(ST));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = newcapacity;
	}

	//插入数据
	pst->a[pst->top] = x;
	pst->top++;
}

//栈顶删除
void STPop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	pst->top--;
}

//显示栈顶元素
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

	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;
}

Test.c

c 复制代码
#include"Stack.h"

int main()
{
	ST s;
	STInit(&s);
	STPush(&s, 1);
	STPush(&s, 2);
	STPush(&s, 3);
	STPush(&s, 4);
	STPush(&s, 5);

	while (!STEmpty(&s))
	{
		printf("%d  ", STTop(&s));
		STPop(&s);
	}
	printf("\n");

	return 0;
}

结果演示


好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

相关推荐
syzyc3 小时前
[ABC267F] Exactly K Steps
数据结构·动态规划·题解
草莓熊Lotso5 小时前
【数据结构初阶】--顺序表(二)
c语言·数据结构·经验分享·其他
汤姆爱耗儿药5 小时前
数据结构——散列表
数据结构·散列表
秋说5 小时前
【PTA数据结构 | C语言版】出栈序列的合法性
c语言·数据结构·算法
hi0_66 小时前
03 数组 VS 链表
java·数据结构·c++·笔记·算法·链表
ChoSeitaku6 小时前
NO.3数据结构栈和队列|顺序栈|共享栈|链栈|顺序队|循环队列|链队|双端队列|括号匹配|中缀表达式转后缀|后缀表达式求值
数据结构·microsoft
皮卡蛋炒饭.7 小时前
数据结构—排序
数据结构·算法·排序算法
??tobenewyorker8 小时前
力扣打卡第23天 二叉搜索树中的众数
数据结构·算法·leetcode
艾莉丝努力练剑12 小时前
【C语言】学习过程教训与经验杂谈:思想准备、知识回顾(五)
c语言·开发语言·数据结构·学习·算法
xienda12 小时前
冒泡、选择、插入排序:三大基础排序算法深度解析(C语言实现)
数据结构·算法·排序算法