一,引言
1,栈作为一种后进先出的数据结构,本文将纤细讲解栈的实现和代码讲解。首先准备工作,通过一个结构体结构体内部嵌套数组,以及两个整型变量来控制数组容量的大小以及插入值的位置,具体如下图:
typedef int STDataType;
typedef struct Stack
{STDataType* _a;int _top; // 栈顶int _capacity; // 容量
}Stack;
2,本文的assert函数用来判断指针是否为空。
基于这个结构体来实现如下函数:
二,栈的初始化
1,函数原型:
void StackInit(Stack* ps);
通过结构体指针来找到结构体。
2,代码实现:
void StackInit(Stack* ps)
{assert(ps);ps->_a = NULL;ps->_capacity = ps->_top = 0;}
主要作用就是将数组置空,数据归零。
三,入栈
1,函数原型:
void StackPush(Stack* ps, STDataType data)
将数据传入数组。
2,代码实现:
void StackPush(Stack* ps, STDataType data)
{assert(ps);if (ps->_capacity == ps->_top){int tem = ps->_capacity == 0 ? 4 : ps->_capacity * 2;STDataType* com = (STDataType*)realloc(ps->_a, sizeof(STDataType) * tem);if (com == NULL){perror("realloc");return;}ps->_a = com;}ps->_a[ps->_top] = data;ps->_top++;
}
需要注意的是需要先进行内存判定,也就是是否还有 空间,若没有需要进行动态进行内存申
请通过perror函数进行判断是否申请成功,最后进行赋值。
3,测试样例以及结果:
int main()
{Stack* ps = (Stack*)malloc(sizeof(Stack));StackInit(ps);StackPush(ps, 2);StackPush(ps, 3);StackPush(ps, 4);return 0;
}
四,出栈
1,函数原型:
void StackPop(Stack* ps);
传入结构体指针。
2,代码实现:
void StackPop(Stack* ps)
{assert(ps);ps->_top --;
}
这里注意的是并没有对数组进行改变,单单通过减少top参数来进行出栈。
3,测试样例及结果:
int main()
{Stack* ps = (Stack*)malloc(sizeof(Stack));StackInit(ps);StackPush(ps, 2);StackPush(ps, 3);StackPush(ps, 4);StackPop(ps);return 0;
}
这里发现只要_top发生变化,数组并没有改变。
五,获取栈顶元素
1,函数原型:
STDataType StackTop(Stack* ps);
通过传入结构体指针,返回栈顶的值。
2,代码实现:
STDataType StackTop(Stack* ps)
{assert(ps);return ps->_a[ps->_top - 1];
}
注意这里返回的(_top-1)并不是(top),因为入栈之后会进行(_top++)会指向最后数据的下一个位置。
3,测试样例及结果:
int main()
{Stack* ps = (Stack*)malloc(sizeof(Stack));StackInit(ps);StackPush(ps, 2);StackPush(ps, 3);StackPush(ps, 4);int a = StackTop(ps);return 0;
}
六,获取栈中有效元素个数
1,函数原型:
int StackSize(Stack* ps);
返回的是栈中有多少个元素。
2,代码实现:
int StackSize(Stack* ps)
{assert(ps);return ps->_top;
}
通过返回top参数直接返回个数
3,测试样例及结果:
int main()
{Stack* ps = (Stack*)malloc(sizeof(Stack));StackInit(ps);StackPush(ps, 2);StackPush(ps, 3);StackPush(ps, 4);int a = StackSize(ps);return 0;
}
七,检测栈是否为空,如果为空返回非零结果,如果不为空返回0
1,函数原型:
int StackEmpty(Stack* ps);
2,代码实现:
int StackEmpty(Stack* ps)
{assert(ps);if (ps->_top == 0){return 1;}return 0;
}
通过if语句进行判断。
3,测试样例及结果:
int main()
{Stack* ps = (Stack*)malloc(sizeof(Stack));StackInit(ps);StackPush(ps, 2);StackPush(ps, 3);StackPush(ps, 4);int a = StackEmpty(ps);return 0;
}
八,销毁栈
通过释放数组空间后调用初始化,这里就不进行详细书写。
九,练习
本文给学者提供接口给有需要的进行练习
#include<stdio.h>
#include <stdlib.h>
#include <assert.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);
// 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
int StackEmpty(Stack* ps);
// 销毁栈
void StackDestroy(Stack* ps);
十,总结
栈总体来说必单链表还是要简单许多,只要经过多加练习,就可以完整的实现。