一、栈的概念及结构
栈是一种特殊的线性表,它只允许在一端进行数据的插入和删除操作,这个进行插入和删除的一端被称为栈顶,另一端称为栈底;栈中的元素遵守后进先出的原则LIFPO(last in first out)
压栈:栈的插入操作叫做压栈\入栈\进栈,入数据在栈顶;
出栈:栈的删除操作叫做出栈,出数据在栈顶。
二、栈的实现
栈的实现可以用数组或者是链表;数组更方便栈的删除和插入数据,因为数组在尾部删除和插入数据是便捷的;用单链表时,实现栈的删除和插入数据需要利用单链表的头插,而双向链表实现栈时,可以直接尾删尾插;
一般实现栈利用的是数组,因为数组实现入栈和出栈的代价比较小;首先在实现栈的这一方面,数组相对于单链表更直接,相对于双向链表则是更为简洁,节省空间(双向链表指针域有两个)。
1、 相关头文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef int DataType;
//栈
typedef struct Stack
{
DataType* data;
int top;
int capacity;
}Stack;
//栈的初始化
void StackInit(Stack* pst);
//栈的销毁
void StackDestroy(Stack* pst);
//栈入数据
void StackPush(Stack* pst, DataType x);
//栈出数据
void StackPop(Stack* pst);
//栈的判空
bool StackEmpty(Stack* pst);
//返回栈顶数据
DataType StackTop(Stack* pst);
//栈中的元素个数
int StackSize(Stack* pst);
2、各个接口的实现
栈的初始化
//栈的初始化
void StackInit(Stack* pst)
{
assert(pst);
pst->data = NULL;
pst->capacity = pst->top = 0;
}
栈的销毁
//栈的销毁
void StackDestroy(Stack* pst)
{
assert(pst);
if (pst->data != NULL)//free不能释放NULL
{
free(pst->data);
}
pst->data = NULL;
pst->capacity = pst->top = 0;
}
入栈
//栈入数据
void StackPush(Stack* pst, DataType x)
{
assert(pst);
int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
if (pst->capacity == pst->top)//空间不够,申请空间
{
DataType* tmp = (DataType*)realloc(pst->data, sizeof(DataType) * newcapacity);
if (tmp == NULL)
{
perror("malloc fail");
return;
}
pst->data = tmp;//realloc自动释放掉旧的空间
pst->capacity = newcapacity;
}
pst->data[pst->top++] = x;
}
出栈
//栈出数据
void StackPop(Stack* pst)
{
assert(pst);
pst->top--;
}
栈的判空
//栈的判空
bool StackEmpty(Stack* pst)
{
assert(pst);
return pst->top == 0 ? true : false;
}
返回栈顶元素
//返回栈顶数据
DataType StackTop(Stack* pst)
{
assert(pst);
return pst->data[pst->top - 1];
}
返回栈中的元素个数
//栈中元素个数
int StackSize(Stack* pst)
{
assert(pst);
return pst->top;
}
top初始化为0,指向的始终是栈顶元素的下一个,相当于顺序表里面的size;
若是把top初始化为-1,那么它指向的就是栈顶元素。