栈: 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出(LIFO)(Last In First Out)的原则。
栈的实现一般可以用数组或链表实现,但是相对而言数组的结构实现会更好,因为数组在尾插数据的代价更小,更便捷。
typedef int STDatatype;
typedef struct Stack {
STDatatype* a;
int top; // 栈顶的位置
int capacity; //栈的容量
}Stack;
在这里我们用数组模拟实现栈。 首先创建一个Stack的结构体,里面分别是数组(这里用指针代替数组,是为了栈可以动态增长的,而不是静态的)、栈顶的位置和栈的容量。
(在这里我们将int 重定义为STDatatype 可以方便修改数据类型,比如说你想把数据类型改成char 只需要在将typedef后的int改成char即可 而不用把其他全部修改)
接下来让我们看看栈需要哪些接口函数:
①:栈的初始化:
void StackInit(Stack* ps) {
ps->a = (STDatatype*)malloc(sizeof(STDatatype)*4);
if (ps->a == NULL) {
printf("初始化栈失败咯");
exit(-1);
}
ps->capacity = 4;
ps->top = 0;
}
先用malloc给数组动态内存开辟4个STDatatype的空间(注意判断空间是否开辟成功),然后将栈容量置为4,栈顶位置为0(未插入元素)。
②:入栈函数的实现
void StackPush(Stack* ps, STDatatype x) {
assert(ps);
if (ps->capacity == ps->top)//检测是否需要增容
{
STDatatype* new = (STDatatype*)realloc(ps->a, sizeof(STDatatype) * ps->capacity * 2);
if (new == NULL) {
printf("增容失败!!");
exit(-1);
}
ps->capacity *= 2;
ps->a = new;
}
ps->a[ps->top] = x;
ps->top++;
}
前面提到栈的结构特点是LIFO(Last In First Out):故栈只能进行尾插与尾删。
先判断是否需要增容,若内存已满则增容。
将ps->top位置的值置为x后再将x++ 即完成了入栈函数。
③:出栈函数
void StackPop(Stack* ps){
assert(ps);
if (ps->top == 0) {
return;
}
ps->top--;
}
注意判断栈中是否还有元素,若没有则直接返回(注意:也可以直接用assert(ps->top != 0)进行暴力检查)
元素出栈只需要将ps->top--即可,下次入栈的元素会自动覆盖已“出栈”的元素。
④:返回栈顶元素:
assert断言确保栈中有元素
STDatatype StackTop(Stack* ps) {
assert(ps);
assert(ps->top > 0);
return ps->a[ps->top-1];
}
注意:ps->top-1才能找到栈顶元素 top 为0表示空栈。
⑤:栈中数据元素个数的函数
int StackSize(Stack* ps) {
assert(ps);
return ps->top;
}
⑥:判断栈是否为空:
不需要用if判断 直接return ps->top == 0 的结果即可!
bool StackEmpty(Stack* ps) {
assert(ps);
return ps->top == 0;
}
⑦:栈的销毁:
void StackDestroy(Stack* ps){
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
至此,我们就完成了栈的实现。