大家好,我是苏貝,本篇博客带大家了解栈,如果你觉得我写的还不错的话,可以给我一个赞吗,感谢❤️

目录

一 .栈的概念及结构二 .栈的实现栈的结构体初始化销毁栈顶插入栈顶删除显示栈顶元素是否为空栈的大小

三. 模块化代码实现Stack.hStack.cTest.c结果演示

一 .栈的概念及结构

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

二 .栈的实现

栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些,因为数组在尾上插入数据的代价比较小(数组的尾插、尾删很方便)。所以下面我们用数组来实现

1

栈的结构体

typedef int STDataType;

#define N 10

typedef struct Stack

{

STDataType _a[N];

int top; // 栈顶

}ST;

上面是定长的静态栈的结构,实际中一般不实用,所以我们主要实现下面的支持动态增长的栈

typedef int STDataType;

typedef struct Stack

{

STDataType* a;

int top;//栈顶

int capacity;//容量

}ST;

2

初始化

因为我们要对ST类型的变量进行初始化,所以实参要传ST类型变量的地址,用一级指针来接收。因为实参(ST类型变量的地址)不可能为NULL,所以对它断言(下面的接口同理)。 注意:我们这里的top指的是栈顶元素的下一个,而非栈顶元素,所以将它初始化为0

void STInit(ST* pst)

{

assert(pst);

pst->a = NULL;

pst->capacity = 0;

pst->top = 0;//指向栈顶元素的下一个

}

3

销毁

注意:在这里我们使用的是动态开辟内存,所以要在销毁时释放掉动态开辟的内存,也就是pst->a指向的那个数组

void STDestroy(ST* pst)

{

assert(pst);

if (pst->a != NULL)

{

free(pst->a);

pst->a = NULL;

pst->capacity = 0;

pst->top = 0;

}

}

4

栈顶插入

再插入元素之前我们要先判断是否要增容,因为在初始化时我们将pst->capacity初始化为0,所以在增容时要特别注意将pst->capacity==0的情况。还要注意对realloc的结果进行判断,防止realloc失败返回NULL,又直接将NULL赋值给pst->a,这样就再找不到开辟的数组了。 最后不要忘记pst->top++

void STPush(ST* pst, STDataType x)

{

assert(pst);

//判断是否需要增容

if (pst->top == pst->capacity)

{

int newcapacity = (pst->capacity == 0) ? 4 : 2 * pst->capacity;

ST* tmp = (ST*)realloc(pst->a, newcapacity * sizeof(ST));

if (tmp == NULL)

{

perror("realloc fail");

return;

}

pst->a = tmp;

pst->capacity = newcapacity;

}

//插入数据

pst->a[pst->top] = x;

pst->top++;

}

5

栈顶删除

删除时我们必须保证栈内有元素,所以要对pst->top>0断言,如果top==0,表示栈内已无元素,返回错误信息,下面的显示栈顶元素同理

void STPop(ST* pst)

{

assert(pst);

assert(pst->top > 0);

pst->top--;

}

6

显示栈顶元素

STDataType STTop(ST* pst)

{

assert(pst);

assert(pst->top > 0);

return pst->a[pst->top - 1];

}

7

是否为空

bool STEmpty(ST* pst)

{

assert(pst);

return pst->top == 0;

}

8

栈的大小

int STSize(ST* pst)

{

assert(pst);

return pst->top;

}

三. 模块化代码实现

Stack.h

#include

#include

#include

typedef int STDataType;

typedef struct Stack

{

STDataType* a;

int top;

int capacity;

}ST;

//初始化

void STInit(ST* pst);

//销毁

void STDestroy(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

#include"Stack.h"

//初始化

void STInit(ST* pst)

{

assert(pst);

pst->a = NULL;

pst->capacity = 0;

pst->top = 0;//指向栈顶元素的下一个

}

//销毁

void STDestroy(ST* pst)

{

assert(pst);

if (pst->a != NULL)

{

free(pst->a);

pst->a = NULL;

pst->capacity = 0;

pst->top = 0;

}

}

//栈顶插入

void STPush(ST* pst, STDataType x)

{

assert(pst);

//判断是否需要增容

if (pst->top == pst->capacity)

{

int newcapacity = (pst->capacity == 0) ? 4 : 2 * pst->capacity;

ST* tmp = (ST*)realloc(pst->a, newcapacity * sizeof(ST));

if (tmp == NULL)

{

perror("realloc fail");

return;

}

pst->a = tmp;

pst->capacity = newcapacity;

}

//插入数据

pst->a[pst->top] = x;

pst->top++;

}

//栈顶删除

void STPop(ST* pst)

{

assert(pst);

assert(pst->top > 0);

pst->top--;

}

//显示栈顶元素

STDataType STTop(ST* pst)

{

assert(pst);

assert(pst->top > 0);

return pst->a[pst->top - 1];

}

//是否为空

bool STEmpty(ST* pst)

{

assert(pst);

return pst->top == 0;

}

//大小

int STSize(ST* pst)

{

assert(pst);

return pst->top;

}

Test.c

#include"Stack.h"

int main()

{

ST s;

STInit(&s);

STPush(&s, 1);

STPush(&s, 2);

STPush(&s, 3);

STPush(&s, 4);

STPush(&s, 5);

while (!STEmpty(&s))

{

printf("%d ", STTop(&s));

STPop(&s);

}

printf("\n");

return 0;

}

结果演示

好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞吗,感谢看到这里,我们下篇博客见❤️

文章来源

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: