当前位置:网站首页>leetCode-栈类型详解
leetCode-栈类型详解
2022-06-28 22:26:00 【ZNineSun】
在刷题的时候遇到一个后缀表达式的题目,然后感觉该题是比较经典的栈应用类型的题目,正好借着该题,给大家聊一聊栈的用法,顺便解决了这道题。
众所周知,栈是是一个先进后出的数据结构,利用该特性,在程序的设计中十分常见,如:括号匹配、表达式求值、在递归中的应用等都离不开栈这一数据结构。
我下面一一给大家简单说一下。(PS:栈的数据结构我就不再此处赘述,大家可以自行了解)
1.栈在括号匹配中的应用
假设表达式中允许包含两种括号 :|直|括号和方括号 ,其嵌套 的顺序任意 即([]())或[([][ ])]等均为正确的格式,[(])或([())或(()]均为不正确的格式 。
我们考虑下列括号序列:
我们简单分析一下:
- 计算机接收第1个括号“ [ ” 后 ,期待与之匹配的第 8 个括号“ ]” 出现 。
- 获得了第 2 个括号 “(”,此时第1 个括号“[” 暂时放在一边,而急迫期待与之匹配的第7 个括号“)”出现 。
- 获得了第 3 个括号“ [ ”,此时第 2 个括 号“(” 暂时放在一边,而急迫期待与之匹配的第4 个括号“]”出现 。第 3 个括号 的期待得到满足,消解之后 ,第 2 个括号 的期待匹配又成为 当前最急迫的任务。
- 以此类推,可见该处理过程与栈的思想、吻合。
我们就按照上面的过程,可以给出以下设计思想:
- 初始化一个堆栈stack,开始依次扫描括号字符串string,当遇到[ ’ 、 ( ’ 左括号时将其压入栈中。
- 当遇到右括号时将检查栈顶元素是否为与此右括号对应的左括号,若对应,则将其对应左括号出栈,若不对应,则表达式有误,返回false。
- 在过程中只有左括号才会压入栈内,当表达式正确时,最后栈将一次次左括号出栈而变为空栈。
- 扫描完所有字符后,检查堆栈是否为空栈,若是,返回true,否则返回false。
题目来源:20. 有效的括号
答案:(PS:Java版)
public boolean isValid(String s) {
Stack<Character> stack = new Stack<Character>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (stack.isEmpty()) return false;
char topChar = stack.pop();
if (c == ')' && topChar != '(') return false;
if (c == ']' && topChar != '[') return false;
if (c == '}' && topChar != '{') return false;
}
}
//判断是否栈空
if (stack.isEmpty()) return true;
return false;
}
2.栈在表达式求值中的应用
表达式求值是程序设计语言编译 中 一个最基本 的问题,它的实现是找应用的一个典型范例 。
中缀表达式不仅依赖运算符的优先级,而且还要处理括号 。后缀表达式的运算符在操作数后面,在后缀表达式中己考虑了运算符的优先级,没有括号,只有操作数和运算符。
中缀表达式A+B*(C-D)-E/F所对应的后缀表达式为ABCD-*EF/-。
里面就涉及到一个知识点,中缀即我们正常的运算顺序如何变为后缀表达式呢?如果你数据结构学的还不错可以跳过该节。
2.1 中缀表达式转化为后缀表达式
我直接举个例子吧。
中缀表达式 a+b - a* ( (c+d) /e- f) + g
这个式子应该相对比较有代表性了,我们就看看怎么把它变成后缀的。
我们先确定好运算符的优先级,即 ‘*,/’ > ‘±’>‘()’
对于(),左括号只有在遇到右括号则表示括号匹配成功,直接退栈,左括号遇到其他字符,直接进栈。
右括号,在遇到其他字符,会让其他字符一直退栈,一直退到左括号为止,和左括号一同出栈,不进行输出。
下面我们的操作步骤就是:遇到优先级大的,直接进栈,遇到优先级小的或者相等的就退栈(PS:如果符号一样,无需操作,直接进栈),同时让优先级进栈。
同时,如果遇到数值则直接输出
下面我们看看:a+b - a* ( (c+d) /e- f) + g这个式子的后缀是怎么一步步实现的
| 步骤 | 扫描项 | 项类型 | 动作 | 栈内容 | 输出 |
|---|---|---|---|---|---|
| 1 | a | 数值 | 直接输出 | 空 | a |
| 2 | + | 操作符 | 栈空,无须比较优先级,进栈 | + | 无输出 |
| 3 | b | 数值 | 直接输出 | + | b |
| 4 | - | 操作符 | +和-优先级相同,先执行退栈,即输出+,在让-进栈 | - | + |
| 5 | a | 操作数 | 直接输出 | - | a |
| 6 | * | 操作符 | *比-优先级高,直接进栈 | -* | 无输出 |
| 7 | ( | 操作符 | 直接进栈 | -*( | 无输出 |
| 8 | ( | 操作符 | 直接进栈 | -*(( | 无输出 |
| 9 | c | 操作数 | 直接输出 | -*(( | c |
| 10 | + | 操作符 | +优先级>(,直接入栈 | -*((+ | 无输出 |
| 11 | d | 操作数 | 直接输出 | -*((+ | d |
| 12 | ) | 操作符 | 让栈顶元素退栈,直至遇到(为止 | -*( | + |
| 13 | / | 操作符 | 优先级比(高,进栈 | -*(/ | 无输出 |
| 14 | e | 操作数 | 直接输出 | -*(/ | e |
| 15 | - | 操作符 | -比/优先级低,/退栈,-进栈 | -*(- | / |
| 16 | f | 操作数 | 直接输出 | -*(- | f |
| 17 | ) | 操作符 | 让栈顶元素一直输出,同时和(一起退栈 | -* | - |
| 18 | + | 操作符 | 优先级比*低,*退栈并输出,和-优先级相同,-退栈并输出,+进栈 | + | * - |
| 19 | g | 操作数 | 直接输出 | + | g |
| 20 | 扫描字符串结束,让栈内元素依次退栈 | - | 直接退栈输出 | 空栈 | + |
最后将输出元素依次连接起来:
ab+acd+e/f-*-g+
这个式子就是我们的后缀表达式
2.2 后缀表达式的计算
最后开始进行计算,而我们最经常使用的便是通过后缀表达式计算最终结果,计算过程如下:
| 步骤 | 扫描项 | 项类型 | 动作 | 栈内容 |
|---|---|---|---|---|
| 1 | - | - | 置空栈 | 空 |
| 2 | a | 操作数 | 进栈 | a |
| 2 | b | 操作数 | 进栈 | a b |
| 3 | + | 操作符 | b,a依次退栈,计算结果b+a,结果r1进栈 | r1 |
| 4 | a | 操作数 | 进栈 | r1 a |
| 5 | c | 操作数 | 进栈 | r1 a c |
| 6 | d | 操作数 | 进栈 | r1 a c d |
| 7 | + | 操作符 | d,c依次退栈,计算结果d+c,结果r2进栈 | r1 a r2 |
| 8 | e | 操作数 | 进栈 | r1 a r2 e |
| 9 | / | 操作符 | e,r2依次退栈,计算e/r2,结果r3进栈 | r1 a r3 |
| 10 | f | 操作数 | 直接进栈 | r1 a r3 f |
| 11 | - | 操作符 | f,r3依次退栈,计算f-r3,结果r4进栈 | r1 a r4 |
| 12 | * | 操作符 | r4 a依次退栈,计算a*r4,结果r5进栈 | r1 r5 |
| 13 | - | 操作符 | r5,r1依次退栈,计算r5-r1,结果r6进栈 | r6 |
| 14 | g | 操作数 | 进栈 | r6 g |
| 15 | + | 操作符 | g r6依次退栈,计算g+r6,结果r7进栈 | r7 |
最终的结果即为栈中的最后一个元素。
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<Integer>();
int n = tokens.length;
for (int i = 0; i < n; i++) {
String token = tokens[i];
if (isNumber(token)) {
stack.push(Integer.parseInt(token));
} else {
int num2 = stack.pop();
int num1 = stack.pop();
switch (token) {
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 / num2);
break;
default:
}
}
}
return stack.pop();
}
public boolean isNumber(String token) {
return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
}
边栏推荐
- VR全景制作的前景如何?
- Ingénieur natif du nuage après 00: utiliser Zadig pour développer des sources ouvertes et des économies d'énergie pour la technologie innovante (bus de Guangzhou)
- 职场人调研报告:裸辞占比最高的居然是中年人
- [gateway development] handle the IP address segment represented by CIDR when NGX nested Lua
- What does project management really manage?
- C#/VB. Net to convert PDF to excel
- 计数排序的简单理解
- 时间序列预测系列文章总结(代码使用方法)
- Qsrand, srand random number generating function in qt5.15 has been discarded
- Quartz定时任务触发器启动时设置
猜你喜欢

【selenium自动化过程中的api抓包】browsermobproxy的安装和配置

Basic knowledge diagram of K-line Diagram -- meaning of single K-line

科技巨头成立元宇宙标准论坛,走向开放还是建立围城?

FANUC机器人_KAREL编程入门(2)_通用IO信号的使用方法

Zadig 面向开发者的自测联调子环境技术方案详解

Zadig + SonarQube,为开发过程安全保驾

台式机没声音怎么样才能解决

时间序列预测系列文章总结(代码使用方法)

Description détaillée du schéma technique du sous - environnement syntonique auto - test de Zadig pour les développeurs

爱数SMART 2022峰会开启,分享数据战略与建设数据驱动型组织方法论
随机推荐
How to analyze the trend chart of London gold market with the moving average
FANUC机器人_KAREL编程入门(2)_通用IO信号的使用方法
00 后云原生工程师:用 Zadig 为思创科技(广州公交)研发开源节流
解读 | 数据分析的发展和演变都经过哪几个阶段?
ansible生产环境使用场景(七):批量部署elk客户端
Considerations on the construction of operation and maintenance system - stability
Ansible production environment usage scenario (7): batch deployment of elk clients
oracle设置密码复杂度及设置超时退出的功能
Career consultation | what should I answer when I am asked about my intended salary during the interview?
In the era of industrial Internet, the Internet in the traditional sense will evolve into many new forms
windows mysql5.7 开启binlog日志
Qsrand, srand random number generating function in qt5.15 has been discarded
What is low code development?
Common tool classes and Commons class libraries
职场进阶 | 了解岗位优势三板斧之“进场”
The example application of histogram in data visualization makes the public performance results clear at a glance
The love digital smart 2022 summit opens, sharing data strategy and building data-driven organization methodology
如何制作精美的图片
Implementation of go language plug-in platform
With the development of industrial Internet as the starting point, the industry can enter a new stage of development