数据结构-栈(带图)

目录

栈的概念

画图理解栈

栈的实现

fun.h

fun.c

main.c


栈的概念

栈(Stack)是一种基本的数据结构,其特点是只允许在同一端进行插入和删除操作,这一端被称为栈顶。遵循后进先出(Last In, First Out, LIFO)原则,即最后存入栈中的元素最先被取出。形象地讲,栈就像是生活中堆放盘子的架子,我们总是把新的盘子放在最上面,而需要拿盘子时也是从最上面开始拿。

生活中就有栈的一些例子比如这些图片:

栈的基本操作包括

  1. 压栈(Push):向栈顶添加一个元素。相当于在堆叠的顶部放入一个新的物品。
  2. 出栈(Pop):从栈顶移除一个元素,并可选择返回这个元素。这类似于从堆叠顶部移走最上面的物品。
  3. 查看栈顶元素(Peek/Top):获取栈顶的元素但不移除它,用于检查或获取栈顶的信息。
  4. 判断栈是否为空(IsEmpty):检查栈中是否有元素。
  5. 获取栈的大小(Size):返回栈中元素的数量

画图理解栈

首先我们栈有一个原理:先进后出,后进先出,于是我们得得到这么个图


开始压栈,压栈的同时我们的p指针也要同时往后面走


最总


出栈


依次出栈后

这里为什么会1 2 3 4压栈出栈后变成了4321?

其实正确的压栈出栈我们需要边压栈边出栈就不会出现这种情况了,所以我main函数中是这样写的

int main1() {
	Stack p;
	STInit(&p);//初始化栈
	StackPush(&p, 1);//压栈
	StackPop(&p);//出栈
	printf("%d\n", p.a[p.top]);
	StackPush(&p, 2);
	StackPop(&p);
	printf("%d\n", p.a[p.top]);
	StackPush(&p, 3);
	StackPop(&p);
	printf("%d\n", p.a[p.top]);	
}

栈的实现

接下来我们用代码实现栈,这里我用了三个文件,解析都在注释中

fun.h

这个文件里有我实现了栈的一些功能

#pragma once
//头文件
#include<stdlib.h>
#include<stdbool.h>
#include<stdio.h>
#include<assert.h>

typedef int STDataType;
//栈的结构
typedef struct Stack
{
	STDataType* a;//指针
	int top;//栈顶
	int capacity;//容量
}Stack;

// 初始化栈 
void StackInit(Stack* ps);
// 入栈 
void StackPush(Stack* ps, STDataType data);
// 出栈 
void StackPop(Stack* ps);
// 获取栈顶元素 
STDataType StackTop(Stack* ps);
// 获取栈中有效元素个数 
int StackSize(Stack* ps);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0 
bool StackEmpty(Stack* ps);
// 销毁栈 
void StackDestroy(Stack* ps);

fun.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"fun.h"

//扩容函数
void Exp(Stack* p) {
	if (p->capacity == p->top)
	{
		//利用三目运算来判断是否
		int New_cap = p->capacity == 0 ? 4 : p->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(p->a, New_cap * sizeof(STDataType));
		if (tmp == NULL)
		{
			assert("realloc");
			return;
		}
		//将开辟空间给给原来的变量
		p->a = tmp;
		p->capacity = New_cap;
	}
}

//初始化
void StackInit(Stack* p) {
	assert(p);
	p->a = NULL;
	p->capacity = p->top = 0;
}
// 入栈 
void StackPush(Stack* p, STDataType data){
	assert(p);
	//判断空间
	Exp(p);
	//入栈
	p->a[p->top] = data;
	//入栈后栈顶向上移动
	p->top++;
}
//出栈
void StackPop(Stack* p) {
	assert(p);
	assert(p->top > 0);//确保不为空

	//判断是否元素是否为0,避免越界 
	/*if (p->top == 0)
	{
		return;
	}*/
	p->top--;
}
// 获取栈顶元素 
STDataType StackTop(Stack* p) {
	//判断是否为0
	if (p->top == 0)
	{
		return (STDataType)0;//由于返回类型是 STDataType,所以需要强制转换
	}
	return p->a[p->top - 1];
}
// 获取栈中有效元素个数 
int StackSize(Stack* p) {
	return p->top;

}
//判空
bool StackEmpty(Stack* p) {
	// 使用逻辑非操作符(!)来检查栈顶指针(top)是否为0(即栈是否为空)
	// 如果top为0,说明栈中没有任何元素,因此栈是空的
	// 在C语言中,逻辑非操作符会将0转换为1(true),非0转换为0(false)
	// 所以当栈顶指针top为0时,!p->top的结果为true(非零值),表示栈为空
	// 反之,如果栈中有元素(top非0),则!p->top的结果为false(0),表示栈非空
	return !p->top;
}
// 销毁栈 
void StackDestroy(Stack* p) {
	if (p->a)
	{
		free(p->a);
		p->a = NULL;
		p->capacity = p->top = 0;
	}
}

main.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"fun.h"
//
//int main1() {
//	Stack p;
//	STInit(&p);
//	StackPush(&p, 1);
//	StackPop(&p);
//	printf("%d\n", p.a[p.top]);
//	StackPush(&p, 2);
//	StackPop(&p);
//	printf("%d\n", p.a[p.top]);
//	StackPush(&p, 3);
//	StackPop(&p);
//	printf("%d\n", p.a[p.top]);
//	
//	
//}

int main() { 
	Stack s1;
	StackInit(&s1);
	StackPush(&s1, 1);
	StackPush(&s1, 2);
	printf("栈中元素个数:%d个\n", StackSize(&s1));
	while (!StackEmpty(&s1))
	{
		printf("%d\n", StackTop(&s1));
		StackPop(&s1);
	}
	printf("栈中元素个数:%d个", StackSize(&s1));
	StackDestroy(&s1);
}

这个数据结构比较简单,里面的很多方法,都是和顺序表差不多,不懂得铁铁可以去看一下我前面的博客

数据结构:顺序表-CSDN博客文章浏览阅读838次,点赞18次,收藏9次。数据是计算机科学中的基本概念,它代表了在计算机程序中处理的一切信息内容。https://blog.csdn.net/2302_78381559/article/details/137435691这边可能你还是不是很理解栈,我们可以试着做一道Leetcode的题,来感受一下栈

题的链接

20. 有效的括号 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/valid-parentheses/description/

我对这道题理解之后写的一篇博客,供大家观看

20. 有效的括号 - 力扣(LeetCode)icon-default.png?t=N7T8https://leetcode.cn/problems/valid-parentheses/description/

  • 54
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

普通young man

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

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

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

打赏作者

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

抵扣说明:

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

余额充值