栈的基础结构
栈是一种基于先进后出(Last-In-First-Out,LIFO)原则的线性数据结构,其结构特点包括:
1.只能在栈顶进行插入(压栈)和删除(弹栈)操作,因此栈是一种顺序访问结构。
2.在栈顶进行插入和删除操作的时间复杂度都是 O(1),即常数级别的复杂度。
3.栈底一般是固定的,栈顶可以动态变化。
因此我们可以得到栈的结构定义如下
typedef int STDataTyep;
typedef struct Stack
{
STDataTyep* data;//在这里我们选择数组来处理栈这一结构,便于尾插
int top;
int capacity;
}ST;
栈的数据操作
①初始化栈
//初始化栈
void STInit(ST* ps)
{
ps->data = (STDataTyep* )malloc(sizeof(STDataTyep) * 10);
if (ps->data == NULL)
{
perror("malloc fail");
return;
}
ps->capacity = 10;
ps->top = 0;
}
②打印栈中元素
//打印栈中元素
void STPrint(ST* ps)
{
int tmp = ps->top-1;
while (tmp != -1)
{
printf("%d <= ", ps->data[tmp]);
tmp--;
}
printf("tail\n");
}
③栈顶插入数据
//栈顶插入数据
void STPush(ST* ps, STDataTyep x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDataTyep* tmp = (STDataTyep*)realloc(ps->data, sizeof(STDataTyep) * (ps->capacity) * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->data = tmp;
ps->capacity *= 2;
}
ps->data[ps->top] = x;
(ps->top)++;
}
④栈顶弹出数据
//栈顶弹出数据
void STPop(ST* ps)
{
assert(ps);
assert(STEmpty(ps));
ps->top--;
}
⑤判断栈中是否为空
//判断栈中元素是否为空
bool STEmpty(ST* ps)
{
return ps->top != 0;
}
⑥销毁栈
//销毁栈
void STDestroy(ST* ps)
{
assert(ps);
free(ps->data);
ps->data = NULL;
ps->capacity = 0;
ps->top = 0;
}
⑦取得栈顶元素
//得到栈顶元素
STDataTyep STTopData(ST* ps)
{
return ps->data[ps->top-1];
}
⑧取得栈中元素个数
//得到栈中元素个数
int STSize(ST* ps)
{
int count = 0;
int tmp = ps->top;
while (tmp)
{
count++;
tmp--;
}
return count;
}
栈的优势与劣势
①优点
⑴栈是一种高效的数据结构,因为它在内存中使用连续的地址,所以它的存取速度非常快。
⑵栈是一种后进先出(LIFO)的数据结构,所以它非常适合于一些需要回溯或撤销操作的场合,例如函数调用栈。
⑶栈的实现非常简单,通常只需要使用一个指针和一些基本操作(如 push 和 pop)就可以完成。
②缺点
⑴栈的大小通常是固定的,所以当栈空间不足时,程序可能会崩溃。
⑵栈中存储的数据通常是临时的,一旦从栈中弹出,就无法再访问。如果需要存储长期数据,则需要使用堆等其他数据结构。
⑶栈中存储的数据大小必须是已知的,否则可能会导致栈溢出等错误。
总的来说,栈是一种非常高效和简单的数据结构,适合用于一些需要回溯或撤销操作的场合,但是它的容量和存储时间都有一些限制,因此在使用时需要谨慎处理。