【数据结构】_栈

在这里插入图片描述
hello 友友们🤗🤗🤗
今天我们要开始进入栈和队列的学习啦~

你们准备好了吗?🧐🧐
下面我们开始吧~GO!

1.栈的概念及结构

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

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

在这里插入图片描述

实现栈建议用什么结构?
数组

在实现之前我们先做两道题叭

  1. 一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是( B )
    A 12345ABCDE
    B EDCBA54321
    C ABCDE12345
    D 54321EDCBA

后进先出 1 2 3 4 5 A B C D E进了那就E 依次出来

  1. 若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是( C )
    A 1,4,3,2
    B 2,3,4,1
    C 3,1,4,2
    D 3,4,2,1

A.1先进了然后出来,2 3 4依次进入,然后4 3 2依次出来符合出栈序列
B.1 2进2出,3进3出,4进4出,然后再1出(符合)
C.1 2 3进,3出,然后选项中要1出,不可能,因为1出之前2要先出
D.1 2 3进,3出,4进4出,然后2 1出

2.栈的实现

2.1接口实现

#pragma once
#include<assert.h>
#include<stdio.h>
#include<stdlib.h>


typedef int STDataType;
//定义一个栈
typedef struct Stack
{
	STDataType* _a;//带_表示成员(数组)
	int _top;//表示栈顶下标(也就是数据个数)
	int _capacity;//动态增长(容量大小)
}Stack;

//初始化
void StackInit(Stack* pst);
//销毁
void StackDestory(Stack* pst);
//入栈(栈顶推入数据)
void StackPush(Stack* pst, STDataType x);
//出栈(栈顶出数据)
void StackPop(Stack* pst);
// 获取栈中数据个数
int StackSize(Stack* pst);

//返回1是空,返回0是非空
int StackEmpty(Stack* pst);

// 获取栈顶的数据
STDataType StackTop(Stack* pst);

2.2初始化

//初始化
void StackInit(Stack* pst)
{
	assert(pst);
	pst->_a = malloc(sizeof(STDataType) * 4);
	pst->_top = 0;//表示栈顶是最后一个数据的下一个位置,初始化为-1表示栈顶就是最后一个数据位置
	pst->_capacity = 4;
}

在这里插入图片描述

2.3销毁

//销毁
void StackDestory(Stack* pst)
{
	assert(pst);
	free(pst->_a);
	pst->_a = NULL;
	pst->_top = pst->_capacity = 0;
}

2.4入栈

//入栈(栈顶推入数据)
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);
	//容量满了(空间不够)要增容
	if (pst->_top == pst->_capacity)
	{
		pst->_capacity *= 2;
		STDataType* tmp = (STDataType*)realloc(pst->_a, sizeof(STDataType)*pst->_capacity);
		if (tmp == NULL)
		{
			printf("内存不足\n");
			exit(-1);
		}
		else
		{
			pst->_a = tmp;//将扩容后的空间给它
		}
	}
	pst->_a[pst->_top] = x;
	pst->_top++;
}

代码分析:

  • 内存重新分配:使用realloc函数对栈的内存空间进行扩容。realloc 函数会尝试将原有的内存块pst->_a调整为新的大小 sizeof(STDataType)*pst->_capacity。如果扩容成功,realloc 会返回一个指向新内存块的指针;如果失败,会返回 NULL。这里将返回的指针赋值给临时指针 tmp
  • 元素入栈:将传入的元素x存储到栈的当前栈顶位置 pst->_a[pst->_top],然后将栈顶指针pst->_top 1,表示栈顶位置向上移动了一个位置。

注意:

解释 sizeof(STDataType) * pst->_capacity 的作用

sizeof(STDataType)sizeofC语言中的一个操作符,它会返回其操作数所占用的字节数STDataType 是栈中元素的数据类型,sizeof(STDataType) 就表示一个栈元素所占用的字节数。
pst->_capacitypst->_capacity 代表栈当前的容量,也就是栈能够容纳的元素数量。
sizeof(STDataType) * pst- > _capacity :二者相乘就得到了栈扩容后总共需要的内存字节数。
举例来说,若 STDataType 是 int 类型,pst->_capacity 为 8,那么 sizeof(STDataType)*pst->_capacity 就等于 4 * 8 = 32 字节,这就是扩容后栈需要的内存大小。

2.5出栈

//出栈(栈顶出数据)
void StackPop(Stack* pst)
{
	assert(pst);
	assert(pst->_top > 0);
	--pst->_top;
}

2.6获取栈中数据个数

// 获取栈中数据个数
int StackSize(Stack* pst)
{
	assert(pst);
	return pst->_top;//返回下标
}

代码解释:
在栈的实现里,_top 变量一般用于标记栈顶元素的下一个位置。栈是从下标0开始存储数据的,那么当栈中有n个元素时,_top 的值就为 n。所以直接返回pst->_top就可以得到栈中数据的个数。

2.7检测栈是否为空

//返回1是空,返回0是非空
int StackEmpty(Stack* pst)
{
	assert(pst);
	return pst->_top == 0 ? 1 : 0;//注意这里不要写成=0 否则会出现严重错误
	//如果是空栈也就是=0为真 返回1,如果非空!=0也就是返回0
}

2.8获取栈顶的数据

// 获取栈顶的数据
STDataType StackTop(Stack* pst)
{
	assert(pst);
	assert(pst->_top > 0);
	//不为空才能调用
	return pst->_a[pst->_top - 1];
	//这里为什么要-1呢??
	//因为top表示栈顶位置,而存储的有效元素个数在栈顶前面
}

2.9如何打印栈

void TestStack()
{
	Stack st;                // 定义栈变量
	StackInit(&st);          // 初始化栈

	StackPush(&st, 1);       // 压入 1
	StackPush(&st, 2);       // 压入 2
	StackPush(&st, 3);       // 压入 3
	StackPush(&st, 4);       // 压入 4

	while (!StackEmpty(&st)) // 只要栈不为空
	{
		printf("%d ", StackTop(&st)); // 打印栈顶元素
		StackPop(&st);       // 弹出栈顶元素
	}
	printf("\n");

	StackDestory(&st);       // 销毁栈
}

int main()
{
	TestStack();
	return 0;
}

注意:这里要先读取再移除 也就是StackTop(&st) 和 StackPop(&st) 的顺序不可颠倒

  • StackTop(&st) 只是读取栈顶元素,不会改变栈结构。

  • StackPop(&st) 才会真正移除栈顶元素。

最后打印结果:
在这里插入图片描述
🎉🎉🎉
在这里本章就结束啦~

在这里插入图片描述
我们下期见~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值