=== 栈 EP1:C++符号配对的艺术 ===
(本文除代码部分均为AI生成,我觉得AI写的还挺好的。)
大家好,欢迎来到我的技术博客!
今天我们开启一个新的系列——《栈》。作为第一集(EP1),我们将通过一个非常经典且实用的问题,来探索 C++ 中 std::stack 的强大之处:如何判断一个字符串中的符号是否正确配对?
这个问题在编程中无处不在,比如检查你写的代码中,那一层又一层的括号是否都正确闭合了。让我们开始吧!
问题:有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,我们需要判断字符串是否“有效”。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
例如,"()[]{}" 和 "{[]}" 都是有效的,而 "(]" 和 "([)]" 则是无效的。
我们的英雄:栈 (Stack)
要解决这个问题,我们需要请出我们的英雄——栈 (Stack)。
栈是一种遵循“后进先出”(Last-In, First-Out, LIFO)原则的数据结构。你可以把它想象成一个只有一个开口的瓶子或者一摞盘子:你最后放进去的盘子,总是最先被拿出来。
这个特性完美地契合了括号配对的逻辑:最晚出现的左括号,应该最先被它对应的右括号配对并“消除”。
C++ 实战代码
废话不多说,我们直接上代码。这是我们用C++ std::stack 实现的完整解决方案:
#include <string>
#include <iostream>
#include <stack> // 包含栈的头文件
bool isValid(std::string s){
std::stack<char> parentheses; // 创建名为parentheses,类型为char的栈。注意这里char要用<char>
for(char c : s) // C++特色,遍历字符串中的每个字符
{
if(c == '(' || c == '[' || c == '{'){
parentheses.push(c); // 左括号入栈!!!!!
}
else{ // 执行到这里说明c是右括号
if(parentheses.empty()){
return false; // 此时栈里无元素,c无法与之配对,所以返回false
}
char top = parentheses.top(); // 栈里存在左括号,取最顶层的左括号
if((top == '(' && c == ')' ) ||
(top == '[' && c == ']') ||
(top == '{' && c == '}'))
{
parentheses.pop(); // 左右括号成功配对,将栈顶的左括号“弹出”
}
else{
return false; // 配对失败返回false
}
}
}
return parentheses.empty(); // 到这一步说明字符串已经遍历完毕,最后检查是否有未配对的左括号。
// 如果栈为空,说明全部配对成功,返回true;否则说明有剩余,返回false。
}
int main()
{
std::string s1 = "[{}]";
std::string s2 = "[[]}";
std::cout << s1 << " is " << (isValid(s1) ? "true" : "false") << std::endl;
std::cout << s2 << " is " << (isValid(s2) ? "true" : "false") << std::endl;
return 0;
}
代码逻辑详解
-
引入头文件与创建栈 我们首先需要
#include <stack>。然后在函数isValid中,通过std::stack<char> parentheses;创建了一个专门存放字符的栈。 -
遍历字符串
for(char c : s)是C++11引入的“基于范围的for循环”,它会帮我们依次取出字符串s中的每一个字符,非常方便。 -
遇到左括号:入栈 当
c是一个左括号 ((,[,{) 时,我们的策略很简单:把它推入(push)栈中。这就像在说:“嘿,我遇到了一个需要被匹配的左括号,先存起来等它的另一半”。 - 遇到右括号:核心匹配逻辑
这是算法最精彩的部分。当
c是一个右括号时:- 检查栈是否为空:
if(parentheses.empty())。如果此时栈是空的,却来了一个右括号,说明这个右括号是多余的,根本没有左括号可以和它配对。直接判定为无效,返回false。 - 查看栈顶元素:如果栈不空,我们用
parentheses.top()方法看一眼栈顶的元素是什么,但不把它拿出来。 - 判断是否配对:我们检查栈顶的左括号是否和当前的右括号是完美的一对。如果是,就调用
parentheses.pop()将栈顶的左括号弹出,代表它们成功“抵消”了。 - 配对失败:如果类型不匹配,说明字符串无效,返回
false。
- 检查栈是否为空:
- 最后的检查
当整个字符串都遍历完毕后,我们还需要做最后一步检查:
return parentheses.empty();。- 如果此时栈是空的,说明所有左括号都被成功匹配并弹出了,字符串有效,函数返回
true。 - 如果栈不是空的,说明还有多余的左括号(如
"((("这种情况)没有被匹配,字符串无效,函数返回false。
- 如果此时栈是空的,说明所有左括号都被成功匹配并弹出了,字符串有效,函数返回
结语
通过这个例子,我们可以看到栈结构在处理具有“层级”或“配对”关系问题时的巨大威力。它清晰、高效地解决了括号匹配问题。
希望这篇 栈EP1 能帮助你更好地理解 std::stack 的使用。在下一集,我们或许可以探讨栈在其他场景下的更多应用,敬请期待!
PS:panda dev-c++复制单行代码可以按住ctrl点home和end键,然后复制。 然后我觉得我现在对于bool这块不是特别熟。