文章目录
(一)栈定义(二)栈实现(1)创建结构体(2)具体函数实现及解析(1.1)初始化栈(1.2)入栈(1.3)出栈(1.4)获取栈顶元素(1.5)获取栈中有效元素个数(1.6)检测栈是否为空(1.7)销毁栈 (三)栈实现代码(1)Stack.c(2)Stack.h(3)test.c (四)栈结构测试结果
(一)栈定义
栈:是一种受限制的线性表,即只能在尾部进行插入、删除的线性表,而且是一种先进后出的数据结构。尾部这一端又叫做栈顶,另一端叫做栈底。
入栈:向一个栈内插入元素叫做入栈或压栈,它把新元素放到栈顶元素的上面,是它成为新的栈顶元素。
出栈:在栈内删除元素叫出栈或退站,即把栈顶元素删除掉,使其相邻的的元素成为新的栈顶元素。
栈的实现一般用数组或链表实现,但数组结构实现更优,因为数组在尾部插入删除的代价小。
如图:数组的入栈和出栈,满足后进先出
类似于枪的子弹夹,后进的去子弹先发射出来,前面的子弹才可以发射出来。
(二)栈实现
(1)创建结构体
typedef int STDataType;// 动态栈typedef struct Stack{STDataType* a;int top;// 栈顶int capacity; // 容量 }Stack;
typedef int STDataType为了方便改类型,栈结构需要创建三个成员变量,STDataType* a,方便增容用指针的形式,top表示栈顶,capacity表示栈容量。
(2)具体函数实现及解析
(1.1)初始化栈
void StackInit(Stack* ps)// 初始化栈 {ps->a = (STDataType*)malloc(sizeof(STDataType)*4);ps->top = 0;ps->capacity = 4;}
初始化先先开辟4个空间,方便增容,置栈顶为0,表示指向栈顶的下一个元素,而capacity置为4。
(1.2)入栈
void StackPush(Stack* ps, STDataType data)// 入栈 {assert(ps);if (ps->top == ps->capacity){STDataType* tmp = (STDataType*)realloc(ps->a,ps->capacity*sizeof(STDataType)* 2);if (tmp == NULL){perror("realloc fail");exit(-1);}ps ->a = tmp;ps->capacity *= 2;}ps->a[ps->top] = data;ps->top++;}
入栈先断言结构体指针不能为空,再判断是否要增容,如果top等于capacity就增,用realloc函数进行增容,增2倍,放到tmp指针变量里,判断tmp是否为空,不为空则把a指向tmp指针,并更新capacity。再把数据放到ps->top下标位置,并++使栈顶指向下一个元素。
(1.3)出栈
void StackPop(Stack* ps)// 出栈 {assert(ps);assert(!StackEmpty(ps));ps->top--;}
出栈的情况直接top–,使栈顶位置往下走,需要两处重要的断言,一是ps不能为空,二是因为这里的栈是不能为空的,我们调用StackEmpty函数啊,如果为空返回真再取反,为假,则报错。
(1.4)获取栈顶元素
STDataType StackTop(Stack* ps)// 获取栈顶元素{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];}
因为ps->top指的是栈顶元素下一个位置,我们取栈顶元素时需要减一,同样需要两处断言,同上。
(1.5)获取栈中有效元素个数
int StackSize(Stack* ps)// 获取栈中有效元素个数 {assert(ps);return ps->top;}
返回个数,直接返回的是ps->top,因为这是数组是从0开始的,所以直接返回即可。
(1.6)检测栈是否为空
bool StackEmpty(Stack* ps)// 检测栈是否为空0 {assert(ps);return ps->top == 0;}
判断是否为空,先断言,直接返回表达式,如果等于0为空,返回true,反之返回false。
(1.7)销毁栈
void StackDestroy(Stack* ps)// 销毁栈 {assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;}
销毁栈,先释放指针a所指向的空间,再把它置为空指针,后两个变量皆置为0。
(三)栈实现代码
(1)Stack.c
#include"Stack.h"void StackInit(Stack* ps)// 初始化栈 {ps->a = (STDataType*)malloc(sizeof(STDataType)*4);ps->top = 0;ps->capacity = 4;}void StackPush(Stack* ps, STDataType data)// 入栈 {assert(ps);if (ps->top == ps->capacity){STDataType* tmp = (STDataType*)realloc(ps->a,ps->capacity*sizeof(STDataType)* 2);if (tmp == NULL){perror("realloc fail");exit(-1);}ps ->a = tmp;ps->capacity *= 2;}ps->a[ps->top] = data;ps->top++;}void StackPop(Stack* ps)// 出栈 {assert(ps);assert(!StackEmpty(ps));ps->top--;}STDataType StackTop(Stack* ps)// 获取栈顶元素{assert(ps);assert(!StackEmpty(ps));return ps->a[ps->top - 1];}int StackSize(Stack* ps)// 获取栈中有效元素个数 {assert(ps);return ps->top;}bool StackEmpty(Stack* ps)// 检测栈是否为空0 {assert(ps);return ps->top == 0;}void StackDestroy(Stack* ps)// 销毁栈 {assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->top = 0;}
(2)Stack.h
#pragma once#include<stdio.h>#include<stdlib.h>#include<assert.h>#include<stdbool.h>typedef int STDataType;// 动态栈typedef struct Stack{STDataType* a;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);// 获取栈中有效元素个数 bool StackEmpty(Stack* ps);// 检测栈是否为空void StackDestroy(Stack* ps);// 销毁栈
(3)test.c
#include"Stack.h"void test1(){Stack st;StackInit(&st);StackPush(&st, 1);StackPush(&st, 2);StackPush(&st, 3);StackPush(&st, 4);StackPush(&st, 5);StackPush(&st, 6);printf("size:%d\n", StackSize(&st)); StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);StackPop(&st);printf("%d\n", StackTop(&st));StackDestroy(&st);}int main(){test1();return 0;}