【数据结构】栈(stack)

写在前面

本篇文章开始讲解栈的有关知识,其实把顺序表和链表学好,那么这一章便不在话下,栈实际上就是顺序表或链表的一些特殊情况。

  • 用顺序表实现的栈叫做顺序栈

  • 用链表实现的栈叫做链栈

文章的内容分为几个部分,希望读者能快速了解文章的脉络架构:

  1. 栈的存储结构——即用结构体定义,包括顺序表栈和链栈

  1. 栈的基本操作——入栈和出栈

  1. 栈的应用——完整的可执行程序(利用前面的基本操作)

  1. 栈的经典力扣题推荐


先识概念

  1. 允许插入和删除的一端叫做栈顶(top),另一端叫做栈底(bottom)

  1. 栈和递归联系紧密,可以用栈来模拟递归的实现过程

  1. 更多知识,还是翻书为妙、


再看思想

顺序存储结构

#define MAXSIZE 100
#define OK 1
#define ERROR 0

typedef int Status;
typedef int ElemType;

//顺序栈存储结构
typedef struct
{
	ElemType data[MAXSIZE];
	int top;
}SqStack;

//进栈
Status Push(SqStack* S, ElemType e)
{
	//栈满
	if (S->top == MAXSIZE - 1)
		return ERROR;
	S->top++;
	//将新插入的元素赋值给栈顶
	S->data[S->top] = e;
	return OK;
}
/*
1.函数参数接收,一个结构体类型的指针大S,一个int型变量e
2.首先判断那把移动的标尺top(我们将其下标存入其中)是否等于最大值-1,栈满的情况就不能进栈了
3.再把元素的值存入S的数据域之中
*/

//出栈 
//若栈不空,则删除栈顶元素,用e返回其值
Status Pop(SqStack* S, ElemType* e)
{
	if (S->top == -1)
		return ERROR;
	//将要删除的栈顶元素赋值给e
	*e = S->data[S->top];
	//栈顶指针-1
	S->top--;
	return OK;
}
/*
1.函数参数接收,一个结构体类型的指针变量大S,一个整型指针类型的变量e
2.我们要出栈,自然栈中得有元素,若没有就结束运行,
3.删除栈顶元素之前,把栈顶结点的数据记录下来,让栈顶计数器top减去1
*/

链栈

//链栈
typedef struct LinkNode
{
	ElemType data;
	struct LinkNode* next;
}LinkNode,*LinkStack;

//进栈
Status Push(LinkStack* S, ElemType e)
{
	//创建新结点
	LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode));
	p->data= e;

	p->next = *S;
	(*S) = p;
	return OK;
}
/*
1.函数参数接收,链栈指针类型的指针变量大S,整型类型的元素e
2.首先我们创建一个新结点,把它的数据域赋值为e,指针域指向栈顶结点
3.让栈顶指针指向p结点,成为新的栈顶结点
*/

//出栈——若栈不为空,则删除S的栈顶元素,用e返回其值
Status Pop(LinkStack *S, ElemType* e)
{
	LinkNode* p;
	if (S==NULL)
		return ERROR;
	*e = (*S)->data;
	//将栈顶结点赋值给p
	p = *S;
	*S = (*S)->next;
	free(p);
	return OK;
}

/*
1.函数参数接收,链栈类型的指针大S,整型指针e
2.如果是空栈就没有出栈的必要,直接返回0,
3.把结点的数据域赋值给e,用临时指针指向栈顶指针,然后把栈顶指针指向栈顶下面的结点(栈的指针由栈顶指向栈底)
4.之后把临时指针所指向的结点释放即可
*/

再学应用

这是一份可运行的入栈和出栈代码,运用了上面的链栈来实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>

#define OK 1
#define ERROR 0

typedef int Status;
typedef int ElemType;

//链栈
typedef struct LinkNode
{
	ElemType data;
	struct LinkNode* next;
}LinkNode, *LinkStack;


Status InitStack(LinkStack* S)
{
	*S = NULL;
	return OK;
}
Status Push(LinkStack* S, ElemType e)
{
	//创建新结点
	LinkNode* p = (LinkNode*)malloc(sizeof(LinkNode));
	p->data = e;

	p->next = *S;
	*S = p;
	return OK;
}

Status Pop(LinkStack* S, ElemType* e)
{
	LinkNode* p;
	if (*S == NULL)
		return ERROR;
	*e = (*S)->data;
	//将栈顶结点赋值给p
	p = (*S);
	*S = (*S)->next;
	free(p);
	return OK;
}

int main()
{
	int i = 0;
	//初始化链栈
	LinkStack S;
	ElemType e;

	InitStack(&S);
	//进栈
	printf("请输入5个整数入栈:");
	for (i = 0; i < 5; i++)
	{
		scanf("%d", &e);
		Push(&S, e);
	}

	//出栈
	printf("依次出栈为:");
	for (i = 0; i < 5; i++)
	{
		Pop(&S, &e);
		printf("%d ", e);
	}

	return 0;
}

写在最后

学完顺序表和链表之后,栈就很简单了,把上面的基础搞懂之后,下一篇文章我们学习后缀表达式以及中缀表达式转后缀表达式和经典栈题目的解答;

232. 用栈实现队列 - 力扣(LeetCode)——简单——放到队列讲完再解答

20. 有效的括号 - 力扣(LeetCode) ——简单

1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)——简单

150. 逆波兰表达式求值 - 力扣(LeetCode)——中等

👍🏻 点赞,你的认可是我创作的动力!
收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

畅游星辰大海

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

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

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

打赏作者

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

抵扣说明:

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

余额充值