目录
一、栈
(1)栈的概念:
(2)压栈及出栈
(3)栈的实现
(4)牛刀小试:
(5)初始化top初始值的俩种情况
二、代码实现
(1)初始化
(2)入栈
(3)删除栈顶数据
(4)获取栈顶元素
(5)检测是否为空
(6)获取栈中有效元素
(7)遍历栈中元素
(8)销毁栈
总代码:
三、有效的括号
是一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作。
进行数据插入和删除的一端称为栈顶,另一端称为栈底。栈中的数据元素遵循后进先出或者先进后出的原则。如图:
压栈:栈的插入操作叫做进栈、压栈或者入栈,从栈顶压入数据
出栈:栈的删除操作叫做出栈。出数据也在栈顶如图 进栈:
如图 出栈:
栈的实现:栈的 实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。因为数组在尾上插入数据的代价比较小
如图 数组栈:
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出 栈的顺序是( )。
A 12345ABCDE B EDCBA54321 C ABCDE12345 D 54321EDCBA
解析:B : 因为是一次入栈,在依次出栈,栈遵循着后进先出的原则,所以出栈的顺序为
EDCBA54321
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是()
A 1,4,3,2 B 2,3,4,1 C 3,1,4,2 D 3,4,2,1
解析:C: 因为进栈的顺序为1234,进栈过程中可以出栈
选项A:1进,然后出,2,3在栈中,4进,出,3出,2出,所以正确
选项B: 1进,2进,出,3进,出,4进,出,最后1出,正确
选项C: 1进,2进,3进,出,栈中还剩1和2,而栈是先进后出的原则,先出1错误,因为栈顶指针指向的是2,不能先出1
选项D:1进,2进,3进,出,4进,出,2出,1出,正确
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;//ps->top = -1;
ps->capacity = 0;
}
//入栈
void StackPush(ST* ps, DataType x)
{
assert(ps);
//考虑如果容量不够的情况
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
DataType* tmp =realloc(ps->a,newcapacity * sizeof(DataType));//a是一个指针,每次访问4个字节,第一次扩了4个 4字节
if (tmp == NULL)
{
printf("realloc failed");
exit(-1);
}
//更新
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
(3)删除栈顶数据
//删除栈顶数据 //因为我们每次访问的是ps->a[top-1]的位置,所以top--访问的是当前top的下一个位置,也就相当于top当前所指向的位置的值被删除了 void StackPop(ST* ps) { assert(ps); assert(ps->top > 0);//top == 1 表示,容量为1,栈顶指针指向0,top == 0表示容量为0,栈顶指针为-1,栈为NULL ps->top--; }
//获取栈顶元素
DataType StackTop(ST* ps)
{
assert(ps);
//方式一:
/*assert(ps->top > 0);*/
//方式二:
assert(!StackEmpty(ps));
return ps->a[ps->top-1];
}
//检测栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
//写法一:
//if (ps->top == 0)
//{
// return true;
//}
//else
// return false;
//写法二:
return ps->top == 0;//top == 0,为1,表示栈为空
}
//获取栈中有效元素
int StackSize(ST* ps)
{
assert(ps);
return ps->top;//top为1,容量为1,如栈顶指向0,top指向他的上一个,也就是1,此时容量为1
}
//遍历栈 void StackPrint(ST* ps) { //遍历栈 while (!StackEmpty(ps))//栈不为空 { printf("%d ", StackTop(ps)); //删除栈顶元素,top--,也就是先将栈顶元素出栈,然后top--,访问下一个 StackPop(ps); } }
效果图:
//销毁栈
void StackDestroy(ST* ps)
{
//将数组的指针释放掉即可
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
stack.h
#pragma once
#include
#include
#include
#include
typedef int DataType;
typedef struct Stack
{
DataType* a;//a相当于一个数组
int top;
int capacity;
}ST;
//初始化
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps,DataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
DataType StackTop(ST* ps);
//获取栈中有效元素
int StackSize(ST* ps);
//检测栈是否为空
bool StackEmpty(ST* ps);
//遍历栈
void StackPrint(ST* ps);
stack.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;//ps->top = -1;
ps->capacity = 0;
}
//入栈
void StackPush(ST* ps, DataType x)
{
assert(ps);
//考虑如果容量不够的情况
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
DataType* tmp =realloc(ps->a,newcapacity * sizeof(DataType));//就是a是一指针,每次访问4个字节,第一次扩了4个 4字节
if (tmp == NULL)
{
printf("realloc failed");
exit(-1);
}
//更新
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//销毁栈
void StackDestroy(ST* ps)
{
//将数组的指针释放掉即可
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
//删除数据
void StackPop(ST* ps)
{
assert(ps);
//写法一:
/*assert(ps->top > 0);*///top == 1 表示,容量为1,栈顶指针指向0,top == 0表示容量为0,栈顶指针为-1,栈为NULL
//写法二:
assert(!StackEmpty(ps));
ps->top--;
}
//获取栈顶元素
DataType StackTop(ST* ps)
{
assert(ps);
//方式一:
/*assert(ps->top > 0);*/
//方式二:
assert(!StackEmpty(ps));
return ps->a[ps->top-1];
}
//检测栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
//写法一:
//if (ps->top == 0)
//{
// return true;
//}
//else
// return false;
//写法二:
return ps->top == 0;//top == 0,为1,表示栈为空
}
//获取栈中有效元素
int StackSize(ST* ps)
{
assert(ps);
return ps->top;//top为1,容量为1,如栈顶指向0,top指向他的上一个,也就是1,此时容量为1
}
//遍历栈
void StackPrint(ST* ps)
{
//遍历栈
while (!StackEmpty(ps))//栈不为空
{
printf("%d ", StackTop(ps));
//删除栈顶元素,top--,也就是先将栈顶元素出栈,然后top--,访问下一个
StackPop(ps);
}
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"stack.h"
void stacktest()
{
ST s1;
StackInit(&s1);
StackPush(&s1,1);
StackPush(&s1,2);
StackPush(&s1,3);
StackPop(&s1);
StackPop(&s1);
//StackPop(&s1);
int a = StackSize(&s1);
printf("%d\n",a);
printf("%d",StackTop(&s1));
StackDestroy(&s1);
}
void stacktest1()
{
ST s2;
StackInit(&s2);
StackPush(&s2, 1);
StackPush(&s2, 2);
StackPush(&s2, 3);
printf("%d ", StackTop(&s2));
StackPop(&s2);
StackPush(&s2,4);
StackPush(&s2,5);
StackPrint(&s2);//遍历栈
StackDestroy(&s2);
}
int main()
{
/*stacktest();*/
stacktest1();
return 0;
}
20. 有效的括号 - 力扣(LeetCode) (leetcode-cn.com)
因为C语言不能直接使用栈,所以要先创建出栈及栈的相关操作:
#include
#include
#include
#include
typedef int DataType;
typedef struct Stack
{
DataType* a;//a相当于一个数组
int top;
int capacity;
}ST;
//初始化
void StackInit(ST* ps);
//销毁栈
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps,DataType x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
DataType StackTop(ST* ps);
//获取栈中有效元素
int StackSize(ST* ps);
//检测栈是否为空
bool StackEmpty(ST* ps);
//遍历栈
void StackPrint(ST* ps);
#define _CRT_SECURE_NO_WARNINGS 1
//初始化
void StackInit(ST* ps)
{
assert(ps);
ps->a = NULL;
ps->top = 0;//ps->top = -1;
ps->capacity = 0;
}
//入栈
void StackPush(ST* ps, DataType x)
{
assert(ps);
//考虑如果容量不够的情况
if (ps->top == ps->capacity)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
DataType* tmp =realloc(ps->a,newcapacity * sizeof(DataType));//就是a是一指针,每次访问4个字节,第一次扩了4个 4字节
if (tmp == NULL)
{
printf("realloc failed");
exit(-1);
}
//更新
ps->a = tmp;
ps->capacity = newcapacity;
}
ps->a[ps->top] = x;
ps->top++;
}
//销毁栈
void StackDestroy(ST* ps)
{
//将数组的指针释放掉即可
free(ps->a);
ps->a = NULL;
ps->capacity = ps->top = 0;
}
//删除数据
void StackPop(ST* ps)
{
assert(ps);
//写法一:
/*assert(ps->top > 0);*///top == 1 表示,容量为1,栈顶指针指向0,top == 0表示容量为0,栈顶指针为-1,栈为NULL
//写法二:
assert(!StackEmpty(ps));
ps->top--;
}
//获取栈顶元素
DataType StackTop(ST* ps)
{
assert(ps);
//方式一:
/*assert(ps->top > 0);*/
//方式二:
assert(!StackEmpty(ps));
return ps->a[ps->top-1];
}
//检测栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
//写法一:
//if (ps->top == 0)
//{
// return true;
//}
//else
// return false;
//写法二:
return ps->top == 0;//top == 0,为1,表示栈为空
}
//获取栈中有效元素
int StackSize(ST* ps)
{
assert(ps);
return ps->top;//top为1,容量为1,如栈顶指向0,top指向他的上一个,也就是1,此时容量为1
}
//遍历栈
void StackPrint(ST* ps)
{
//遍历栈
while (!StackEmpty(ps))//栈不为空
{
printf("%d ", StackTop(ps));
//删除栈顶元素,top--,也就是先将栈顶元素出栈,然后top--,访问下一个
StackPop(ps);
}
}
bool isValid(char * s)
{
ST s1;
StackInit(&s1);
while(*s)//不等于'\0'
{
if(*s == '{' || *s == '[' || *s == '(')
{
StackPush(&s1,*s);
++s;
}
else//是右括号,那么就那么就将栈中的拿出来比较,匹配,s++,继续循环,不匹配,则返回false
{
//特殊情况1:
//如果栈为空,只有]
if(StackEmpty(&s1))
{
StackDestroy(&s1);
return false;
}
DataType top = StackTop(&s1);
StackPop(&s1);//删除栈顶元素
if( (*s == '}' && top != '{' )
||(*s == ']' && top != '[' )
|| (*s == ')' && top != '('))
{
//如果是 ()( ] ]
StackDestroy(&s1);//只要return之前就Destroy,防止内存泄漏
return false;
}
else
{
++s;
}
}
}
//特殊情况2:
//如果只有[,那说明栈不是空,与之不匹配,返回0
bool ret = StackEmpty(&s1);
StackDestroy(&s1);
return ret;
}
运行结果:
本文是我对栈的学习的一些笔记以及自己的一些理解,如有问题,请在评论区多多评论^_^