栈知识梳理和函数实现

参考此文章数据结构——栈,此文章写的更详细,由于我们都是学自于比特课程,这里做个自我备份,方便后续查阅、修改和补充。


前言


1.栈是什么?

在这里插入图片描述

栈(Stack):是只允许在一端进行插入或删除的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。

栈顶(Top):线性表允许进行插入删除的那一端。

栈底(Bottom):固定的,不允许进行插入和删除的另一端。

空栈:不含任何元素的空表。

栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构

2.栈的接口实现

栈与顺序表类似,可设计为定长的静态栈或支持动态增长的栈。然而,定长栈存在较大局限性,在实际中不太实用,因此我们主要实现支持动态增长的栈。

与之前的顺序表/链表接口实现相同,我们首先创建一个头文件“Stack.h”以及两个源文件“Stack.c”和“Test.c”,它们的具体作用如下:

  • “Stack.h”:用于栈的定义、头文件的引用以及接口函数的声明。
  • “Stack.c”:实现接口函数。
  • “Test.c”:对各个函数进行测试。
    我们先完整展示“Stack.h”的代码,同时别忘了在两个源文件中引用“Stack.h”。
#pragma once //防止头文件被二次引用
 
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
 
typedef int STDataType; //如果要修改存储的数据类型可直接在此修改
 
typedef struct Stack 
{
	STDataType* arr;
	int top;
	int capacity; //容量
}Stack;
 
void StackInit(Stack* pst);//初始化栈
 
void StackPush(Stack* pst, STDataType x);//入栈
 
void StackPop(Stack* pst);//出栈
 
STDataType StackTop(Stack* pst);//获取栈顶元素
 
int StackSize(Stack* pst);//获取栈中有效元素个数
 
bool StackEmpty(Stack* pst);//检测栈是否为空
 
void StackDestory(Stack* pst);//销毁栈

2.1初始化栈

void StackInit(Stack* pst)
{
	assert(pst); //断言,防止传入空指针
	pst->arr = NULL; //初始化指针,置空
	pst->top = 0; //top指向栈顶数据的下一个位置
	pst->capacity = 0; //初始化容量
}

类似地,我们可将结构体中的 top 近似理解为数组的下标(虽然并非完全等同,但这样理解较为方便)。当我们在初始化栈时,将 top 初始化为 0,此时栈中无数据,top 指向栈顶数据的下一个位置。在这里插入图片描述
当我们将 top 初始化为 -1 时,top 会指向栈顶数据的位置。
本文我们采用的是 top 初始值为 1 的情况。

2.2入栈

void StackPush(Stack* pst, STDataType x)
{
	if (pst->top == pst->capacity) //容量已满,需要扩容
	{
		int NewCapacity = pst->capacity == 0 ? 4 : pst->capacity * 2; //如果容量为0则扩到4,否则扩为2倍
		STDataType* cmp = (STDataType*)realloc(pst->arr, NewCapacity * sizeof(STDataType));
        //创建一个临时指针变量来存储新空间地址,防止开辟失败
		if (cmp == NULL) //防止空间开辟失败出现空指针
		{
			perror("realloc fail");
			return;
		}
		pst->arr = cmp; //将临时指针变量中存放的新空间地址赋值给arr
		pst->capacity = NewCapacity; //空间容量更新
	}
	pst->arr[pst->top] = x; //将数据存放进栈顶元素的下一个位置
	pst->top++; //位置更新
}

2.3 出栈

void StackPop(Stack* pst)
{
	assert(pst); //断言,防止传入空指针
	assert(!StackEmpty(pst)); //断言,用检测空栈的函数返回值来判断,栈为空则不能出栈
	pst->top--; //位置更新
}

出栈只需要移动top的位置,把原来栈顶的元素“踢出”有效数据范围即可。StackEmpty函数将在后面讲到。

2.4 获取栈顶元素

STDataType StackTop(Stack* pst)
{
	assert(pst); //断言,防止传入空指针
	assert(!StackEmpty(pst)); //断言,用检测空栈的函数返回值来判断,栈为空则不能获取
	return pst->arr[pst->top - 1]; //top-1为栈顶元素位置,返回其值即可
}

2.5 获取栈中有效元素个数

int StackSize(Stack* pst)
{
	assert(pst); //断言,防止传入空指针
	return pst->top; //top即为有效元素个数
}

2.6 检测栈是否为空

bool StackEmpty(Stack* pst)
{
	assert(pst); //断言,防止传入空指针
	return pst->top == 0; //如果top为0表达式则为真,返回值为ture,反之为false
}

2.7销毁栈


bool StackEmpty(Stack* pst)
{
	assert(pst); //断言,防止传入空指针
	return pst->top == 0; //如果top为0表达式则为真,返回值为ture,反之为false
}

2.8 调试代码

所有接口都完成后,我们在Test.c中调试一下

#include "Stack.h"
void TestStack()
{
	ST st;
	StackInit(&st);
	StackPush(&st, 1);
	StackPush(&st, 2);
	StackPush(&st, 3);

	printf("%d ", StackTop(&st));
	StackPop(&st);
	printf("%d ", StackTop(&st));
	StackPop(&st);
	StackPush(&st, 4);
	StackPush(&st, 5);
	while (!StackEmpty(&st))
	{
		printf("%d ", StackTop(&st));
		StackPop(&st);
	}
	printf("\n");

	StackDestory(&st);
}
int main()
{
	TestStack();
	return 0;
}
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值