栈
栈:结构定义
放入元素是从底向上放入
有一个栈顶指针,永远处在栈顶的元素
还需要标记栈大小的size
栈的性质: Fisrt-in Last-out (FILO) 先进后出
栈改变元素的顺序
栈:出栈
让栈顶指针向下移动一位
栈:入栈
栈顶指针向上移动一位,然后把元素放进来
栈:数组实现
结构定义
typedef struct Stack{
int *data;
int size, top;
} Stack;
初始化栈
top指针一开始指向-1
Stack *initStack(int n)
{
Stack *s = (Stack*)malloc(sizeof(Stack));
s->data = (int *)malloc(sizeof(int)* n);
s->size = n;
s->top = -1;
return s;
}
栈判空
// 栈判空
int empty(Stack *s)
{
return s->top == -1;
}
查看栈顶元素
// 查看栈顶元素
int top(Stack *s)
{
if (empty(s)) return 0;
return s->data[s->top];
}
入栈
// 入栈
int push(Stack *s, int val)
{
if (s->top + 1 == s->size) return 0; // 栈是否满了
s->top += 1;
s->data[s->top] = val;
return 1;
}
出栈
// 出栈
int pop(Stack *s)
{
if (empty(s)) return 0;
s->top -= 1;
return 1;
}
销毁栈
// 销毁栈
void clearStack(Stack *s)
{
if (s == NULL) return;
free(s->data);
free(s);
return;
}
栈:代码演示
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
typedef struct Stack{
int *data;
int size, top;
} Stack;
Stack *initStack(int n)
{
Stack *s = (Stack*)malloc(sizeof(Stack));
s->data = (int *)malloc(sizeof(int)* n);
s->size = n;
s->top = -1;
return s;
}
// 栈判空
int empty(Stack *s)
{
return s->top == -1;
}
// 查看栈顶元素
int top(Stack *s)
{
if (empty(s)) return 0;
return s->data[s->top];
}
// 入栈
int push(Stack *s, int val)
{
if (s->top + 1 == s->size) return 0; // 栈是否满了
s->top += 1;
s->data[s->top] = val;
return 1;
}
// 出栈
int pop(Stack *s)
{
if (empty(s)) return 0;
s->top -= 1;
return 1;
}
// 销毁栈
void clearStack(Stack *s)
{
if (s == NULL) return;
free(s->data);
free(s);
return;
}
// 输出栈
void outputStack(Stack *s)
{
printf("Stack: ");
for (int i = s->top; i >= 0; --i)
{
printf("%4d", s->data[i]);
}
printf("\n\n");
return;
}
int main()
{
srand(time(0));
#define MAX_OP 10
Stack *s = initStack(MAX_OP);
for (int i = 0; i < MAX_OP; i++)
{
int op = rand() % 3, val = rand() % 100; // 0: pop; 1, 2: push
switch (op)
{
case 0:
printf("pop stack, item = %d\n", top(s));
pop(s);
break;
case 1:
case 2:
printf("push stack, item = %d\n", val);
push(s, val);
break;
}
outputStack(s);
}
clearStack(s);
std::cin.get();
return 0;
}
测试结果
Leetcode-20. 有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 3:
输入:s = “(]”
输出:false
提示:
1 <= s.length <= 104
s 仅由括号 ‘()[]{}’ 组成
题目解析
怎么判断一个括号序列满足相互包含的相互关系?
一开始,top指针指向-1
碰到左括号"(“,入栈
遇到左括号”{“,继续入栈
遇到右括号,且匹配得上栈顶元素,出栈
遇到右括号,且匹配得上栈顶元素,继续出栈
遇到左括号“[”,入栈
遇到左括号”(“,继续入栈
遇到右括号,且与栈顶元素匹配,出栈
遇到左括号”{",入栈
遇到右括号,且与栈顶元素匹配,出栈
遇到右括号,且与栈顶元素匹配,出栈
最后,栈为空,判定括号序列合法
代码演示
先改写栈的代码,将其从int类型全部改为char类型
typedef struct Stack{
char *data;
int size, top;
} Stack;
Stack *initStack(int n)
{
Stack *s = (Stack*)malloc(sizeof(Stack));
s->data = (char *)malloc(sizeof(char)* n);
s->size = n;
s->top = -1;
return s;
}
// 栈判空
int empty(Stack *s)
{
return s->top == -1;
}
// 查看栈顶元素
char top(Stack *s)
{
if (empty(s)) return 0;
return s->data[s->top];
}
// 入栈
int push(Stack *s, char val)
{
if (s->top + 1 == s->size) return 0; // 栈是否满了
s->top += 1;
s->data[s->top] = val;
return 1;
}
// 出栈
int pop(Stack *s)
{
if (empty(s)) return 0;
s->top -= 1;
return 1;
}
// 销毁栈
void clearStack(Stack *s)
{
if (s == NULL) return;
free(s->data);
free(s);
return;
}
主程序代码
void solve(char str[])
{
int flag = 1; // 是否匹配成功
Stack *s = initStack(100);
// 扫描字符串的每一位
for (int i = 0; str[i]; i++)
{
if (str[i] == '(' || str[i] == '[' || str[i] == '{')
{
push(s, str[i]);
}
else
{
// 判断是否与栈顶元素匹配
switch (str[i])
{
case ')':
if (top(s) == '(') pop(s);
else flag = 0; // 没有匹配成功
break;
case ']':
if (top(s) == '[') pop(s);
else flag = 0;
break;
case '}':
if (top(s) == '{') pop(s);
else flag = 0;
break;
}
if (flag == 0) break;
}
}
if (flag == 0 || !empty(s)) printf("error");
else printf("success\n");
clearStack(s);
}
int main()
{
char str[100];
while (scanf_s("%s", str))
{
solve(str);
}
std::cin.get();
return 0;
}
输入1:([{}]){{{[]}}}{}
输出1:success: ([{}]){{{[]}}}{}
输入2: ((((([]{}[]{}
输出2: error: ((((([]{}[]{}
输入3: (([]{}))))
输出3: error: (([]{}))))
总结
栈的作用:判断括号序列是否合法
括号序列本身是一个完全包含关系,栈就是可以处理这种具有完全包含关系的问题。
参考
ACM大牛带你玩转算法与数据结构
Leetcode