数据结构 - 栈的学习
栈 (Stack) 是一种非常常见的数据结构, 是一种 "先入后出"(First In Last Out, FILO) "后进先出" 的数据结构 (Last In First Out, LIFO)。 也可以把栈看成是一种特殊的线性表,只能在栈顶进行插入和删除操作。 也就是说,对于栈而言,你只能在栈顶进行操作,而栈底是固定的
栈的基本操作,包括 入栈(Push), 出栈(Pop), 取栈顶元素(Top) , 判空 (IsEmpty) 等
栈有顺序栈和链式栈
1. 顺序栈
我们来看看顺序栈的示意图:
顺序栈是一种使用数组实现的栈,也称为数组栈, 也就是说,它是通过数组来存储栈中的元素的, 并且通过栈顶指针来指示栈顶元素在数组中的位置。 顺序栈具有以下特点:
1. 存储结构: 顺序栈使用数组来作为底层的存储结构,栈中的每个元素会作为数组中的一个元素存在
2. 操作顺序: 栈只能够从栈顶插入和删除元素,不支持在栈中间插入和删除元素
3. 顺序访问: 只能从栈顶开始访问栈中的元素,不能从栈底或者中间位置来访问元素
由上面可以看出,顺序栈的实现并不是很难,我们可以通过数组和栈顶指针两个变量来进行实现。 它的一些主要操作包括 初始化,入栈,出栈,获取栈顶元素,判断栈是否为空, 以及获取栈中元素的数量等。
上面也提到,顺序栈的存储结构是数组,因此我们使用时也需要考虑数组大小的限制,当栈中元素数量超过数组大小时,需要对数组进行扩容
时间复杂度:
遍历栈中元素的操作时间复杂度为 O(n)
入栈,出栈,获取栈顶元素,判断栈是否为空 => 这几个操作时间复杂度为 O(1)
现在,我用C++来实现栈的这些基本操作
1. 用结构来定义一个栈
// 栈中的数据类型 typedef int stackType;
#define INITCAPA 5 //栈结构 typedef struct Stack{ stackType *arr; //数组 int top; //栈顶 int capacity; //栈的容量 } ST;
2. 初始化栈
void StackInit(ST *pst) {
assert(pst);
pst->arr = (stackType *)malloc(INITCAPA * sizeof(stackType));
if(pst->arr == NULL)
{
perror("malloc fail");
return;
}
pst->top = 0; // top等于0,指的是栈顶元素的下一个位置
// pst->top = -1; //指的是栈顶元素的位置
pst->capacity = INTICAPA; }
3. 判断空栈
因为在第2步中pst->top赋的初值为0. 所以当 top == 0 时,就表示栈为空
bool StackEmpty(ST* pst) {
assert(pst);
return pst->top == 0; }
4. 入栈
入栈,需要先判断栈满没满,满的条件为 ptr->top == ptr->capacity, 如果栈已经满了,我们还想有元素入栈,那么就需要对栈进行扩容。 扩容的过程和顺序表是一样的
从上面第2步可以知道,top表示的是栈顶元素的下一个位置,所以在top下标处位置进行插入数据就可以。 完成后进行 top++就可以完成一次入栈了
void STPush(ST* pst, stackType newElement) {
assert(pst);
if(pst->capacity == pst->top)
{
stackType* tmp = (stackType*)realloc(pst->arr, sizeof(stackType) * pst->capacity * 2);
if(tmp == NULL)
{
perror("realloc fail");
return;
}
pst->arr = tmp;
pst->capacity *= 2;
}
pst->arr[pst->top] = newElemenet;
pst->top++; }
5. 出栈
出栈,如果栈为空,出栈就会出问题,所以出栈前,我们需要判断一下,栈不为空
上面提到,入栈后top++, 显然,出栈就是top--, 也就是说我们进行 pst->top--, top值减去1,那么在其他所有操作中就访问不到最后一个元素了,也就达到了出栈的效果
void STPop(ST* pst) {
assert(pst);
assert(!StackEmpty(pst));
pst->top--;
}
6. 获取栈顶元素的值
获取栈顶元素的值,显然有个前提条件那就是栈中得有元素存在。如果栈是个空栈,那什么也获取不到,所以获取之前,还是需要使用上面自己写的StackEmpty方法判断一下
从上面可以知道,top表示栈顶元素的下一个位置,所以 top -1才表示栈顶元素的下标, 也就是 pst->arr[pst->top - 1] , 代码如下
stackType STTop(ST* pst) {
assert(pst);
assert(!StackEmpty(pst));
return pst->arr[pst->top -1];
}
7, 销毁
void STDestory(ST* ptr) {
assert(ptr);
free(ptr->arr);
ptr->arr == NULL;
ptr->capacity = 0;
ptr->top = 0; }