目录
一、栈的概念及其结构
二、栈的实现
1.栈的初始化 void STInit(ST* ps);
2.栈的插入 void STPush(ST* ps, STDataType x);
3.栈的删除 void STPop(ST* ps);
4.栈的大小计算 int STSize(ST* ps);
5.判断栈是否为空 bool STEmpty(ST* ps);
6.栈的销毁 void STDestroy(ST* ps);
7.访问栈顶元素 STDataType STTop(ST* ps);
三、栈的操作合集
Stack.h
stack.c
test.c
一、栈的概念及其结构
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。
进行数据插入和删除操作的一端
称为栈顶,另一端称为栈底。
栈中的数据元素遵守后进先出
LIFO
(
Last In First Out
)的原则。
压栈:栈的插入操作叫做进栈
/
压栈
/
入栈,
入数据在栈顶
。
出栈:栈的删除操作叫做出栈。
出数据也在栈顶
。

二、栈的实现
栈的实现一般可以使用
数组或者链表实现
,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。

1.栈的初始化 void STInit(ST* ps);
//栈的初始化
void STInit(ST* ps)
{
assert(ps);
ps->a = malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->capacity = 4;
ps->top = 0;//代表top表示的是栈顶元素的下一个位置:刚开始top指向的是第一个元素,表示0,当第一个元素插入后top++表示1
}
2.栈的插入 void STPush(ST* ps, STDataType x);
//栈的插入
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);//扩容到当前的二倍
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
3.栈的删除 void STPop(ST* ps);
//栈的删除
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
}
在栈操作函数中,栈指针 ps 是操作栈的基础,如果 ps 为 NULL,那么后续对 ps 指向的栈结构的任何访问(如 ps->top)都会导致未定义行为,通常是程序崩溃。因此,在进行栈操作之前,需要先确保 ps 不是 NULL,assert(!STEmpty(ps)); 实际上是在检查栈不为空的情况下才继续执行后续操作
4.栈的大小计算 int STSize(ST* ps);
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
5.判断栈是否为空 bool STEmpty(ST* ps);
//判断栈是否为空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
6.栈的销毁 void STDestroy(ST* ps);
//栈的销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
7.访问栈顶元素 STDataType STTop(ST* ps);
//访问栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top-1];
}
三、栈的操作合集
Stack.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#define N 10
typedef int STDataType;
typedef struct Stack
{
int* a;
int top;//下标
int capacity;
}ST;
//栈的初始化
void STInit(ST* ps);
//栈的插入
void STPush(ST* ps, STDataType x);
//栈的删除
void STPop(ST* ps);
//
int STSize(ST* ps);
//判断栈是否为空
bool STEmpty(ST* ps);
//栈的销毁
void STDestroy(ST* ps);
//访问栈顶元素
STDataType STTop(ST* ps);
//不支持打印,因为不能保证后进先出
stack.c
#include"Stack.h"
//栈的初始化
void STInit(ST* ps)
{
assert(ps);
ps->a = malloc(sizeof(STDataType) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->capacity = 4;
ps->top = 0;//代表top表示的是栈顶元素的下一个位置:刚开始top指向的是第一个元素,表示0,当第一个元素插入后top++表示1
}
//栈的插入
void STPush(ST* ps, STDataType x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * ps->capacity * 2);//扩容到当前的二倍
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
//栈的删除
void STPop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
ps->top--;
/*在栈操作函数中,栈指针 ps 是操作栈的基础,如果 ps 为 NULL,
那么后续对 ps 指向的栈结构的任何访问(如 ps->top)都会导致未定义行为,
通常是程序崩溃。因此,在进行栈操作之前,需要先确保 ps 不是 NULL
assert(!STEmpty(ps)); 实际上是在检查栈不为空的情况下才继续执行后续操作*/
}
//
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
//判断栈是否为空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
//栈的销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = 0;
ps->capacity = 0;
}
//访问栈顶元素
STDataType STTop(ST* ps)
{
assert(ps);
assert(!STEmpty(ps));
return ps->a[ps->top-1];
}
test.c
#include"Stack.h"
int main()
{
ST st;
STInit(&st);
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
STPush(&st, 5);
while (!STEmpty(&st))
{
printf("%d ", STTop(&st));
STPop(&st);
}
STDestroy(&st);
}