目录
栈
概念与结构
栈是一种特殊的线性表,它只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据遵循先进后出的原则。
压栈:栈的插入操作叫做压栈/入栈/进栈。
出栈:栈的删除操作叫做出栈。
出数据和入数据都在栈顶。
栈底层结构选型
数组
链表
那么对于数组和链表我们选择哪个比较好呢?
答案是数组。因为链表虽然动态性更强,但是每个操作都需要动态分配结点,内存开销比较大,且频繁分配/释放可能引发内存碎片。而数组尾插尾删的效率更高。
使用数组实现栈
我们就根据顺序表的结构来模拟一遍栈的结构。
typedef int STDataType;
typedef struct stack
{
STDataType* arr;
int top;
int capacity;
}ST;
初始化栈
void STInit(ST* ps)
{
assert(ps);
ps->arr = NULL;
ps->top = ps->capacity = 0;
}
判断栈空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
入栈
void STCheck(ST* ps)
{
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->arr, newcapacity * sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc failed!");
exit(1);
}
else
{
ps->arr = tmp;
ps->capacity = newcapacity;
}
}
}
void STPush(ST* ps, STDataType x)
{
assert(ps);
STCheck(ps);
ps->arr[ps->top++] = x;
}
出栈
void STPop(ST* ps)
{
assert(ps && ps->arr && !STEmpty(ps));
ps->top--;
}
注意:删除的空间不能free掉,因为动态开辟的空间不能局部释放。
取栈顶元素
STDataType STTop(ST* ps)
{
assert(ps && ps->arr && !STEmpty(ps));
return ps->arr[ps->top-1];
}
栈的元素个数
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->top = ps->capacity = 0;
}