目录
栈(stack)
1.栈的概念:
栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。栈是一种后进先出的(Last In First Out)的线性表,简称LIFO。
可以把栈理解为一个箱子,最早装进去的东西都是压箱底的,只有最后才能拿出来,最晚放进去的是摆在最上面的。
———————————————————————————————————————————
2.代码实现:
①栈的主体选择:
采用顺序表实现栈,好处就是操作更为方便,从顺序表本质来讲,用尾插法实现栈,进栈就是尾插,出栈就是尾删:
因此不用进行头插头删的操作,而且顺序表数组是一片连续的空间,读取速度占优,如果用链表实现栈,尾插法需要通过标记尾结点来提高运行效率,或者是改为头插法提高效率。
②基本结构:(结构体Stack)(顺序表)
typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int top; // 栈顶的位置
int capacity; // 容量
}ST;
结构体Stack中,存有需要的静态数组arr指针,作为栈元素的存储空间,也就是“箱子”。
而top则是表示栈顶元素的arr下标(下标由0开始)。
由于静态数组容量是一次性定量的,我们无法确保数组的空间足够使用,因此我们需要定义整型capacity(容量)来检查数组此时的容量,如果容量不够了,我们可以通过capacity检查,并及时扩容。
———————————————————————————————————————————
③栈的初始化(StackInit)
void StackInit(ST* ps)//栈的初始化
{
assert(ps);
ps->arr = NULL;
ps->top = 0;
ps->capacity = 0;
}
检查传入的Stack结构体ps地址是否为空。
初始化 arr数组地址指向NULL,此时arr没有内容。
top栈顶元素下标指向0;
容量大小也为0;
———————————————————————————————————————————
④进栈(StackPush)(尾插)
void StackPush(ST* ps, STDataType x)//进栈
{
assert(ps);
//
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
ps->arr = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
if (ps->arr == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity;
}
ps->arr[ps->top] = x;
ps->top++;
}
1.还是前面的问题,当静态数组arr当前的容量不足时,我们要进行扩容。
那么我们如何判断arr容量不足?
看栈顶元素下标。
最新进栈的元素,下标是当前元素中最大的,这也是我们判断arr容量不足的方法。
第一种情况:当capacity=0时,即arr无扩容,这时候我们可以进行小量扩容。
第二种情况:当下标top的值与capacity相同时,说明此时arr已经有元素,而且arr已经满了,需要进行扩容。
(第二点需要注意的是;下标top是由0开始的,所以假如arr里最大的下标是3,但此时arr里已经有4个元素了)
完整函数:
void StackPush(ST* ps, STDataType x)//进栈
{
assert(ps);
//
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
ps->arr = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));//扩容
if (ps->arr == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity; //更新capacity大小
}
ps->arr[ps->top] = x;
ps->top++;
}
———————————————————————————————————————————
⑤出栈(StackPop)(尾删)
面对顺序表的尾删,做法可以是把当前存在的下标往前倒一位,这样的话,原来最新的元素没有了使用价值,以至于之后被新的进栈元素覆盖掉。
完整函数:
void StackPop(ST* ps)//出栈
{
assert(ps);
assert(ps->top > 0);
--ps->top;
}
———————————————————————————————————————————
⑥判断是否为空(StackEmpty)
简单判断下标top再返回bool值
完整函数:
bool StackEmpty(ST* ps)//判断是否为空
{
assert(ps);
return ps->top == 0;
}
———————————————————————————————————————————
⑦取栈首位元素(StackTop)
注意项:
上面说过,由于下标从0开始,假如下标top=3,此时arr里就有了4个数组。
而且栈顶元素是下标最大的元素,所以当下标top代表的是栈顶元素后一位的位置。
例:此时arr有四个元素,栈顶元素下标是3,top下标是4。
所以返回栈顶元素,应该是返回[top-1]位置的元素。
STDataType StackTop(ST* ps)//取栈首位元素
{
assert(ps);
assert(ps->top > 0);
return ps->arr[ps->top - 1];
}
———————————————————————————————————————————
⑧栈的长度
例:此时arr有四个元素,栈顶元素下标是3,top下标是4,top刚好对于arr元素个数。
int StackSize(ST* ps)//栈的长度
{
assert(ps);
return ps->top;
}
———————————————————————————————————————————
完整代码:
Stack.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
typedef int STDataType;
typedef struct Stack
{
STDataType* arr;
int top; // 栈顶的位置
int capacity; // 容量
}ST;
void StackInit(ST* ps);
void StackDestory(ST* ps);
void StackPush(ST* ps, STDataType x);
void StackPop(ST* ps);
bool StackEmpty(ST* ps);
int StackSize(ST* ps);
STDataType StackTop(ST* ps);
Stack.c
#include "Stack.h"
void StackInit(ST* ps)//栈的初始化
{
assert(ps);
ps->arr = NULL;
ps->top = 0;
ps->capacity = 0;
}
void StackDestory(ST* ps)//栈销毁
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->capacity = ps->top = 0;
}
void StackPush(ST* ps, STDataType x)//进栈
{
assert(ps);
//
if (ps->top == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
ps->arr = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
if (ps->arr == NULL)
{
printf("realloc fail\n");
exit(-1);
}
ps->capacity = newCapacity;
}
ps->arr[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)//出栈
{
assert(ps);
assert(ps->top > 0);
--ps->top;
}
bool StackEmpty(ST* ps)//判断是否为空
{
assert(ps);
return ps->top == 0;
}
STDataType StackTop(ST* ps)//取栈首位元素
{
assert(ps);
assert(ps->top > 0);
return ps->arr[ps->top - 1];
}
int StackSize(ST* ps)//栈的长度
{
assert(ps);
return ps->top;
}