目录
1.栈
1.1栈的概念和结构
1.2关于栈的概念的两个选择题
1.3栈的实现
1)声明
2)实现
2.栈实现的源代码(vs2022下编译)
3.关于栈的OJ题练习:
1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B)。
A 12345ABCDE
B EDCBA54321
C ABCDE12345
D 54321EDCBA
2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)
A 1,4,3,2
B 2,3,4,1
C 3,1,4,2
D 3,4,2,1栈的出栈顺序不一定非得是数据全部进入完毕后再出,也可以是边进边出。
栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些
因为数组在尾上插入数据的代价比较小。
如果用链表作为栈的话,一般用头做栈顶,尾做栈底,因为链表的头插和头删更有优势
这里我们主要实现数组栈,数组栈分为静态栈和动态栈(和顺序表一样)
静态栈的结构:
typedef int STDataType;
#define N 10
typedef struct Stack
{
STDataType _a[N];
int _top; // 栈顶
}Stack;
动态栈结构:
typedef int STDataType;
typedef struct Stack
{
STDataType* _a;
int _top; // 栈顶,初始为0,表示栈顶下一个位置的下标
int _capacity; // 容量
}ST;
下面以动态栈为例,进行实现
typedef int STDatatype;
typedef struct Stack
{
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置下标
}ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);
//栈中的有效个数
int StackSize(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
//打印
void StackPrant(ST* ps);
1.初始化
void StackInit(ST* ps)
{
assert(ps);
//可以全部初始化NULL和0
//ps->a = NULL;
//ps->top = 0;
//ps->capacity = 0;
//也可以先给其开辟4个空间大小的地址
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
exit(-1);
}
ps->top = 0;
ps->capacity = 4;
}
如果不在初始化这里开辟大小的话,需要在入栈的realloc前加上:
int NewCapacity = p->capacity == 0 ? 4 : p->capacity * 2;
realloc变为:
STDatatype* tmp = (STDatatype*)realloc(ps->a, NewCapacity * sizeof(STDatatype));
realloc在pa->a为NULL时会为其开辟新的空间
2.销毁栈
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
3.入栈
void StackPush(ST* ps, STDatatype x)
{
assert(ps);
// 扩容
//这里注意top是从0开始的,top指向的是顶的下一个,当存放了4个数据后,top=4(0,1,2,3)
if (ps->top == ps->capacity)
{
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
4.出栈
void StackPop(ST* ps)
{
//判断栈是不是为NULL
assert(ps);
//判断栈里面还有没有元素
assert(!StackEmpty(ps));
ps->top--;
}
5.返回栈顶元素
STDatatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//栈顶元素是top-1
return ps->a[ps->top - 1];
}
6.返回栈的元素数量
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
因为数据存储是从0开始的,top是栈顶数据+1,刚好就是我们所说的元素数量
7.判断栈是否为空
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top == 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
8.打印栈
void StackPrant(ST* ps)
{
int i = 0;
while (i != ps->top)
{
printf("%d ", ps->a[i]);
i++;
}
printf("\n");
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
//声明
typedef int STDatatype;
typedef struct Stack
{
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置下标
}ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);
//栈中的有效个数
int StackSize(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
//打印
void StackPrant(ST* ps);
//实现
void StackInit(ST* ps)
{
assert(ps);
//可以全部初始化NULL和0
//ps->a = NULL;
//ps->top = 0;
//ps->capacity = 0;
//也可以先给其开辟4个空间大小的地址
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
exit(-1);
}
ps->top = 0;
ps->capacity = 4;
}
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
void StackPush(ST* ps, STDatatype x)
{
assert(ps);
// 扩容
//这里注意top是从0开始的,top指向的是顶的下一个,当存放了4个数据后,top=4(0,1,2,3)
if (ps->top == ps->capacity)
{
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
/*if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}*/
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
//判断栈是不是为NULL
assert(ps);
//判断栈里面还有没有元素
assert(!StackEmpty(ps));
ps->top--;
}
STDatatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//栈顶元素是top-1
return ps->a[ps->top - 1];
}
int StackSize(ST* ps)
{
assert(ps);
return ps->top;
}
bool StackEmpty(ST* ps)
{
assert(ps);
/*if (ps->top == 0)
{
return true;
}
else
{
return false;
}*/
return ps->top == 0;
}
void StackPrant(ST* ps)
{
int i = 0;
while (i != ps->top)
{
printf("%d ", ps->a[i]);
i++;
}
printf("\n");
}
//测试
void text1()
{
ST ps;
StackInit(&ps);
StackPush(&ps, 1);
StackPush(&ps, 2);
StackPush(&ps, 3);
StackPush(&ps, 4);
StackPush(&ps, 5);
StackPush(&ps, 6);
StackPush(&ps, 7);
StackPush(&ps, 8);
StackPrant(&ps);
int a = StackTop(&ps);
printf("size:%d,栈顶元素为:%d\n", StackSize(&ps),a); // 不关心底层实现,直接用
printf("size:%d\n", ps.top); // 关心底层实现
StackPop(&ps);
StackPop(&ps);
StackPop(&ps);
StackPrant(&ps);
a = StackTop(&ps);
printf("size:%d,栈顶元素为:%d\n", StackSize(&ps), a);
}
int main()
{
text1();
return 0;
}
有效的括号
思路:
代码:
主要实现的函数:
bool isValid(char * s)
{
//创建一个新的栈
ST st;
StackInit(&st);
//如果*s为空退出循环
while(*s)
{
if(*s=='[' || *s=='(' || *s=='{')
{
StackPush(&st,*s);
++s;
}
else
{
//如果数组中只有右括号,直接对栈进行判空操作
if(StackEmpty(&st))
{
StackDestroy(&st);
return false;
}
char top=StackTop(&st);
StackPop(&st);
//不匹配
if( (*s == ']' && top != '[') ||
(*s == ')' && top != '(') ||
(*s == '}' && top != '{') )
{
StackDestroy(&st);
return false;
}
else//继续
{
++s;
}
}
}
//如果,栈里面还剩左括号的元素,则说明不符合要求,所以要对栈进行判空操作
bool ret =StackEmpty(&st);
StackDestroy(&st);
return ret;
}
全部代码:
#include
#include
#include
#include
typedef char STDatatype;
typedef struct Stack
{
STDatatype* a;
int capacity;
int top; // 初始为0,表示栈顶位置下一个位置下标
}ST;
//初始化
void StackInit(ST* ps);
//销毁
void StackDestroy(ST* ps);
//入栈
void StackPush(ST* ps, STDatatype x);
//出栈
void StackPop(ST* ps);
//获取栈顶元素
STDatatype StackTop(ST* ps);
//判断栈是否为空
bool StackEmpty(ST* ps);
void StackInit(ST* ps)
{
assert(ps);
ps->a = (STDatatype*)malloc(sizeof(STDatatype) * 4);
if (ps->a == NULL)
{
perror("malloc fail");
exit(-1);
}
ps->top = 0;
ps->capacity = 4;
}
void StackDestroy(ST* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->top = ps->capacity = 0;
}
void StackPush(ST* ps, STDatatype x)
{
assert(ps);
if (ps->top == ps->capacity)
{
STDatatype* tmp = (STDatatype*)realloc(ps->a, ps->capacity * 2 * sizeof(STDatatype));
ps->a = tmp;
ps->capacity *= 2;
}
ps->a[ps->top] = x;
ps->top++;
}
void StackPop(ST* ps)
{
//判断栈是不是为NULL
assert(ps);
//判断栈里面还有没有元素
assert(!StackEmpty(ps));
ps->top--;
}
STDatatype StackTop(ST* ps)
{
assert(ps);
assert(!StackEmpty(ps));
//栈顶元素是top-1
return ps->a[ps->top - 1];
}
bool StackEmpty(ST* ps)
{
assert(ps);
return ps->top == 0;
}
bool isValid(char * s)
{
//创建一个新的栈
ST st;
StackInit(&st);
//如果*s为空退出循环
while(*s)
{
if(*s=='[' || *s=='(' || *s=='{')
{
StackPush(&st,*s);
++s;
}
else
{
//如果数组中只有右括号,直接对栈进行判空操作
if(StackEmpty(&st))
{
StackDestroy(&st);
return false;
}
char top=StackTop(&st);
StackPop(&st);
//不匹配
if( (*s == ']' && top != '[') ||
(*s == ')' && top != '(') ||
(*s == '}' && top != '{') )
{
StackDestroy(&st);
return false;
}
else//继续
{
++s;
}
}
}
//如果,栈里面还剩左括号的元素,则说明不符合要求,所以要对栈进行判空操作
bool ret =StackEmpty(&st);
StackDestroy(&st);
return ret;
}