数据结构:栈

文章目录

  • 前言
  • 一、栈的概念及其结构
  • 二、栈的实现
    • 1.头文件Stack.h(栈的结构及其声明方法)
    • 2.源文件Stack.c (实现栈的方法:增删查改)
  • 总结


前言

栈(Stack)是一种线性数据结构,具有特殊的操作规则。栈中的数据项按照后进先出(Last In First Out, LIFO)的原则进行插入和删除操作。

栈具有两个主要的操作:

  1. 入栈(Push):在栈顶插入一个元素。如果栈已满,则无法插入新元素。
  2. 出栈(Pop):从栈顶删除一个元素,并返回被删除的元素。如果栈为空,则无法进行删除操作。

栈还具有以下几个概念和特性:

  1. 栈顶(Top):栈中最后插入的元素。
  2. 栈底(Bottom):栈中第一个插入的元素。
  3. 栈的大小(Size):栈中元素的数量。
  4. 栈的空间限制:栈的大小有限,当栈已满时,无法再进行入栈操作。
  5. 栈的空间利用:由于栈的后进先出规则,栈中的元素可以快速插入和删除,因此栈常常用于临时存储、函数调用等场景。

栈可以通过数组或链表来实现。使用数组实现的栈称为顺序栈(Sequential Stack),使用链表实现的栈称为链式栈(Linked Stack)。


一、栈的概念及其结构

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

 

二、栈的实现

1.头文件Stack.h(栈的结构及其声明方法)

利用CPU高速缓存,实现栈我们底层使用数组

#pragma once
#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 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.源文件Stack.c (实现栈的方法:增删查改)

2.1 初始化与销毁

#include"Stack.h"

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

	pst->a = NULL;
	// top指向栈顶数据的下一个位置
	pst->top = 0;

	// top指向栈顶数据
	//pst->top = -1;

	pst->capacity = 0;
}

void STDestroy(ST* pst)
{
	assert(pst);

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

注意:此时top代表的含义,当top为0时是有数据还是没数据,习惯性把top初始化为0,指向栈顶数据下一个位置

2.2 入栈与出栈

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

	// 扩容
	if (pst->top == pst->capacity)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		STDataType* tmp = (STDataType*)realloc(pst->a, newcapacity * sizeof(STDataType));
		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--;
}

a.此时的扩容与之前的顺序表如出一辙,注意三目操作符的使用

b.因为top指向下一个位置数据,所以先插入,后++,与数组下标类似

c.为什么pop代码只有一行也需要创建一个函数?----- 保持接口一致性,避免为空的一些bug

 2.3 取栈顶数据

// 取栈顶数据
STDataType STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);

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

 一定不能为空,返回时注意top指向

 2.4 判空

// 判空
bool STEmpty(ST* pst)
{
	assert(pst);

	return pst->top == 0;
}

当top为0时则为空 

2.5 获取数据个数

// 获取数据个数
int STSize(ST* pst)
{
	assert(pst);

	return pst->top;
}

类比顺序表


总结

栈是一种常见的数据结构,具有先进后出(LIFO)的特点。它的作用主要包括以下几个方面:

1. 内存管理:栈用于管理计算机内存的分配和释放。在程序运行过程中,局部变量、函数调用和返回等操作都会通过栈来管理内存空间。

2. 函数调用:栈用于存储函数调用的相关信息,如函数参数、局部变量和返回地址等。每当一个函数被调用时,相关信息会被压入栈中,函数执行完毕后再从栈中弹出。

3. 表达式计算:栈在表达式计算中起着重要作用。例如,中缀表达式可以通过将其转换为后缀表达式,然后使用栈来计算。栈可以保存操作符和操作数的顺序,便于计算和更新。

4. 后退操作:栈可以用于实现后退操作,例如浏览器的返回功能。当用户点击返回按钮时,浏览器会从栈中弹出最近访问的页面,以实现后退到上一个页面的功能。

5. 括号匹配:栈可以用于检查括号的匹配情况。当遇到左括号时,将其推入栈中;当遇到右括号时,将栈顶的左括号弹出,检查是否匹配。如果最终栈为空,说明括号匹配成功。

总的来说,栈在计算机科学和软件开发中有着广泛的应用,是一种非常重要的数据结构。

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

取加若则_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值