目录
一. 栈的定义与性质
顺序栈是一种后进先出(LIFO)的数据结构,通过动态数组实现,支持动态扩容和收缩。主要操作包括入栈、出栈、获取栈顶元素和判断栈空,适用于需要快速访问最后存入数据的场合。
二. 栈的top指针的位置的选择
方案一:选择top指向栈顶元素的当前位置,那么top指针就只能选择初始化在-1的位置。
方案二:如果选择top指针为栈顶元素的下一个位置,那么top指针初始化为0.
三. 代码实现
3.1 顺序栈
3.1.1 初始化
void STInit(ST* pst)
{
assert(pst);
pst->a = NULL;
pst->capacity = 0;
pst->top = 0;
}
结构体:
typedef int STDataType;
typedef struct Stack
{
int* a;
int top; //标识栈顶的位置data下标
int capacity;
}ST;
如果不懂 int* p,与int *p的区别的小伙伴请移步我的这一篇博客。
C语言,数据结构指针,结构构体操作符 •,->,*的区别,看这篇就够了_*指针->和指针->的区别-CSDN博客
3.1.2 销毁栈
void STDestory(ST* pst)
{
assert(pst);
free(pst->a);
}
3.1.3 入栈
入栈之前要先判断是否空间不够即是否栈满,其次在动态扩容之前要先判断是否容量初始化为0,如果初始化为0那么在就要赋初值为4,否则就直接扩二倍
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, sizeof(STDataType) * newcapacity);
if (tmp == 0)
{;
perror("realloc fail");
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x;
pst->top++;
}
3.1.4 出栈
void STPop(ST* pst)
{
assert(pst);
assert(pst->top > 0);
pst->top--;
}
3.1.5 判空
bool STEmpty(ST* pst)
{
if (pst->top == 0)
return false;
else
return true;
}
测试用例
#define _CRT_SECURE_NO_WARNINGS
#include"stack.h"
int test()
{
ST st;
STInit(&st);
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
printf("%d ",STTop(&st));
STPop(&st);
printf("%d ", STSize(&st));
printf("%d ", STTop(&st));
}
int main()
{
test();
return 0;
}
运行结果
完整代码
//stack.h 文件
#pragma once
// 防止头文件重复包含
#include<stdio.h>
// 引入标准输入输出库
#include<stdlib.h>
// 引入标准库,用于内存分配和释放
#include<stdbool.h>
// 引入标准布尔库,以使用布尔类型
#include<assert.h>
// 引入断言库,用于进行条件检测
typedef int STDataType;
// 定义栈中存储元素的数据类型为整数
typedef struct Stack
{
int* a; // 指向栈的动态数组
int top; // 标识栈顶的位置(即栈中下一个空位的索引)
int capacity; // 栈的当前最大容量
} ST;
// 定义栈的结构体
void STInit(ST* pst);
void STDestory(ST* pst);
void STPush(ST* pst, STDataType x);
void STPop(ST* pst);
STDataType STTop(ST* pst);
bool STEmpty(ST* pst);
int STSize(ST* pst);
// 声明栈操作的各个函数
//stack.c 文件
#define _CRT_SECURE_NO_WARNINGS
// 定义一个宏,用于在Visual Studio环境下禁止某些安全警告
#include "stack.h"
// 包含栈的头文件,通常用于分离声明和实现
// 初始化栈
void STInit(ST* pst)
{
assert(pst); // 断言,确保pst指针非空
pst->a = NULL; // 初始化动态数组指针为NULL
pst->capacity = 0; // 初始化容量为0
pst->top = 0; // 初始化栈顶索引为0
}
// 销毁栈
void STDestory(ST* pst)
{
assert(pst); // 断言,确保pst指针非空
free(pst->a); // 释放动态数组占用的内存
}
// 向栈中插入元素
void STPush(ST* pst, STDataType x)
{
assert(pst); // 断言,确保pst指针非空
// 扩容
if (pst->top == pst->capacity) // 如果栈已满
{
int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2; // 新容量是原容量的两倍,若原容量为0则设为4
STDataType* tmp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
if (tmp == 0)
{
perror("realloc fail"); // 内存分配失败时打印错误信息
return;
}
pst->a = tmp;
pst->capacity = newcapacity;
}
pst->a[pst->top] = x; // 将新元素放入栈顶
pst->top++; // 栈顶索引增加
}
// 从栈中弹出元素
void STPop(ST* pst)
{
assert(pst); // 断言,确保pst指针非空
assert(pst->top > 0);// 断言,确保栈不为空
pst->top--; // 栈顶索引减1
}
// 返回栈顶元素
STDataType STTop(ST* pst)
{
assert(pst); // 断言,确保pst指针非空
assert(pst->top > 0);// 断言,确保栈不为空
return(pst->a[pst->top - 1]); // 返回栈顶元素
}
// 判断栈是否为空
bool STEmpty(ST* pst)
{
return pst->top == 0; // 如果栈顶索引为0,则栈为空
}
// 返回栈的大小
int STSize(ST* pst)
{
assert(pst