一、栈的概念及结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。
进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。
栈中的数据元素遵守
后进先出
LIFO
(
Last In First Out
)的原则。
压栈:栈的插入操作叫做进栈
/
压栈
/
入栈,
入数据在栈顶
。
出栈:栈的删除操作叫做出栈。
出数据也在栈顶
。
二、栈的实现
栈的实现一般可以使用
数组或者链表实现
,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。
接下来我们逐步拆分栈的功能,一个一个模块去实现栈
(1)栈的动态结构
在模拟实现栈时,我们利用一个结构体来实现栈的结构,同时为了满足后续的增删查改的操作,我们选择支持动态增长的栈。
(2)初始化栈(StackInit)
我们利用StackInit函数来初始化栈。其原型为void StackInit(Stack*ps);
在初始化中,我们将top值设置为0,但这是否意味着top指向的是栈顶元素呢?
需要注意的是,在我们将数据存放进arr数组中时,top所指向的是末尾元素的下一位,所以在初始化中,我们要么将top的初始值设为-1,要么在之后的操作中始终保持警惕,注意top指向的元素。
(3)数据的入栈(StackPush)
我们该如何将数据插入到栈中呢?第一步是检查arr的空间是否还有富裕,如果有,直接插入并将top++指向栈顶的下一位,如果没有,那么我们就要进行扩容操作来存放数据。
(4)数据的出栈(StackPop)
数据的出栈操作其实很简单,只要将top值减一就可以了。
(5)返回栈顶数据(StackTop)
注意,这里就需要根据初始化的top值选择不同的方式返回,如果top为0,就需要top-1再返回
(6)返回数据个数(StackSize)
(7)判断栈是否为空(StackEmpty)
(8)销毁栈(StackDestroy)
三、完整代码
stack.h
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
typedef int STDataType;//便于后续数据类型的替换
typedef struct Stack
{
STDataType* arr;//支持动态增长
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);
stack.c
#include "stack.h"
void StackInit(Stack* ps)
{
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
void StackPush(Stack* ps, STDataType data)
{
assert(ps);
if (ps->top == ps->capacity)//检查是否有剩余空间
{
int newcapacity = (ps->capacity == 0) ? 4 : 2 * ps->capacity;
STDataType* pa = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
if (pa == NULL)
{
perror("realloc fail");
return;
}
ps->arr = pa;//扩容操作完成
ps->capacity = newcapacity;//容量数值更改
}
ps->arr[ps->top] = data;//插入数据
ps->top++;
}
void StackPop(Stack* ps)
{
assert(ps->top);
ps->top--;
}
STDataType StackTop(Stack* ps)
{
assert(ps->top);
return ps->arr[ps->top - 1];
}
int StackSize(Stack* ps)
{
assert(ps);
assert(ps->top);
return ps->top;
}
bool StackEmpty(Stack* ps)
{
assert(ps);
return ps->top == 0;
}
void StackDestroy(Stack* ps)
{
if (ps->arr != NULL)
{
free(ps->arr);
ps->arr = NULL;
}
ps->top = ps->capacity = 0;
}