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

其实栈和弹夹是类似的,可以把栈想象成弹夹,就好理解了。
二.栈的存储形式
1.链表存储与顺序表存储的选择
我们来分析分析,用栈存储的优势在哪?
进栈的时候,很OK,时间复杂度是O(1);
用链表不用担心容量不够,扩容的问题。
那不好的地方呢?
出栈时间复杂度是O(N);
取栈顶时间复杂度:O(N);
看完了链表,我们来看看顺序表
优势:
入栈出栈取栈顶的时间复杂度都是O(1)
劣势 :
空间不够需要扩容。
谁优谁劣一目了然,顺序表的时间复杂度和链表都不是一个量级,且需要扩容的问题,在代码运行效率面前,也就无足轻重了。所以,我们选择顺序表。
2.栈的存储形式
我们知道顺序表有静态与动态两种形式,这里选择比较优的方法即动态存储。
typedef int datatype;
typedef struct stack
{
datatype* arr;
int top; //栈顶元素的下一个
int capacity; //容量
}ST;
三.栈的基本操作
1.初始化
我们先给数组4个datatype大小的空间。
void StackInit(ST* ps)
{
assert(ps);
ps->arr = (datatype*)malloc(sizeof(datatype)*4);
ps->capacity = 4;
ps->top = 0;
}
2.入栈
void StackInsert(ST* ps, datatype x)
{
assert(ps);
if (ps->capacity == ps->top) //判断是否需要扩容
{
datatype* new = realloc(ps->arr, 2 * sizeof(datatype) * ps->capacity);
if (new == NULL)
{
perror("realloc fail");
return;
}
ps->arr = new;
ps->capacity *= 2;
}
ps->arr[ps->top] = x;
ps->top++;
}
3.判空
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
{
return true;
}
else
return false;
}
4.取栈顶
datatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->arr[ps->top - 1];
}
5.出栈
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
6.打印
void StackPrint(ST* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->top; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
7.大小
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
8.销毁
void StackDestroy(ST* ps)
{
free(ps->arr);
ps->arr = NULL;
ps->capacity = 0;
ps->top = 0;
}
四.完整代码
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int datatype;
typedef struct stack
{
datatype* arr;
int top;
int capacity;
}ST;
void StackInit(ST*ps);
void StackInsert(ST* ps, datatype x);
bool StackEmpty(ST* ps);
int StackSize(ST* ps);
datatype StackTop(ST* ps);
void StackPop(ST* ps);
void StackPrint(ST* ps);
void STackDestroy(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->arr = (datatype*)malloc(sizeof(datatype)*4);
ps->capacity = 4;
ps->top = 0;
}
void StackInsert(ST* ps, datatype x)
{
assert(ps);
if (ps->capacity == ps->top)
{
datatype* new = realloc(ps->arr, 2 * sizeof(datatype) * ps->capacity);
if (new == NULL)
{
perror("realloc fail");
return;
}
ps->arr = new;
ps->capacity *= 2;
}
ps->arr[ps->top] = x;
ps->top++;
}
bool StackEmpty(ST* ps)
{
assert(ps);
if (ps->top == 0)
{
return true;
}
else
return false;
}
datatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
return ps->arr[ps->top - 1];
}
void StackPop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
ps->top--;
}
void StackPrint(ST* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < ps->top; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
void StackDestroy(ST* ps)
{
free(ps->arr);
ps->arr = NULL;
ps->capacity = 0;
ps->top = 0;
}
int main()
{
ST ps;
StackInit(&ps);
StackInsert(&ps,1);
StackInsert(&ps,2);
StackInsert(&ps,3);
StackPrint(&ps);
datatype x=StackTop(&ps);
printf("%d\n", x);
StackPop(&ps);
int size = StackSize(&ps);
printf("%d\n", size);
StackPrint(&ps);
StackDestroy(&ps);
}