一,栈的概念
栈是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据也在栈顶。
通俗来说就是先进入的数据最后出来,最后进去的数据先出来就比如我们在一个细管子中放入石头,那么最开始放的石头在最底下,最后放的石头就在管口,把石头倒出来,那最先出来的石头就是管口的。
二,栈的结构
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小。由于刚刚上面的定义介绍我们直到,栈这种结构他只能尾插和尾删,所以这种情况下选择数组是非常方便的。他的结构就和顺序表是非常像的。
typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;
这里的top就是栈顶位置的下一个
三,栈的实现
//初始化
void STInit(ST* ps);
//销毁
void STDestroy(ST* ps);
//插入
void STPush(ST* ps, STDataType x);
//删除
void STPop(ST* ps);
//找top位置的数据
STDataType STTop(ST* ps);
//一共有多少个数据
int STSize(ST* ps);
//判断是否为空
bool STEmpty(ST* ps);
3.1栈的初始化
//初始化
void STInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
3.2栈的销毁
//销毁
void STDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
3.3栈的插入
//插入
void STPush(ST* ps, STDataType x)
{
assert(ps);
//先判断容量是否够
if (ps->capacity == ps->top)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDataType* tmp = (STDataType*)realloc(ps->a, sizeof(STDataType) * newcapacity);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->capacity = newcapacity;
ps->a = tmp;
}
ps->a[ps->top] = x;
++ps->top;
}
这里我们判断扩容的函数直接写到了插入里面是因为,栈只有一个插入,而之前的顺序表的时候插入的方式非常多,所以单独分开写梗方便我们去利用。
3.3栈的删除
//删除
void STPop(ST* ps)
{
assert(ps);
assert(ps->top > 0);
--ps->top;
}
3.4栈顶元素的值
//找top位置的数据
STDataType STTop(ST* ps)
{
assert(ps);
return ps->a[ps->top - 1];
}
我们最开始提到top是栈顶元素的下一个位置,所以我们在找栈顶元素的时候,要减一。
3.5计算栈一共的数据
//一共有多少个数据
int STSize(ST* ps)
{
assert(ps);
return ps->top;
}
3.6判断是否为空
//判断是否为空
bool STEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
四,测试
void text1()
{
ST st;
STInit(&st);
STPush(&st, 1);
STPush(&st, 2);
STPush(&st, 3);
STPush(&st, 4);
STPush(&st, 5);
while (!STEmpty(&st))
{
printf("%d ", STTop(&st));
STPop(&st);
}
printf("\n");
STDestroy(&st);
}
int main()
{
text1();
return 0;
}
五,题目练习(有效的括号)
括号匹配问题
5.1分析
我们可以让左括号入栈,右括号出栈,进行比较,同样的要注意左右括号数量也要保持一致。
5.2代码
bool isValid(char * s){
ST st;
STInit(&st);
char topval;
while(*s)
{
//左括号入栈
switch(*s)
{
case '{':
case '[':
case '(':
STPush(&st,*s);
break;
case '}':
case ']':
case ')':
if(STEmpty(&st))
{
STDestroy(&st);
return false;
}
topval=STTop(&st);
STPop(&st);
if(*s=='}'&&topval!='{'
||*s==']'&&topval!='['
||*s==')'&&topval!='(')
{
return false;
}
break;
}
s++;
}
bool val=STEmpty(&st);
STDestroy(&st);
return val;
}