简介: 在C++的标准模板库(STL)中,Stack(栈)是一种常用的容器,它遵循后进先出(LIFO)的原则,即最后进入栈的元素最先被移出栈。Stack提供了一种简单而高效的方式来管理数据,是处理后进先出数据流的理想选择。
特性:
- 后进先出(LIFO):Stack容器遵循后进先出的原则,保证了数据按照插入顺序的相反顺序被处理。
- 简单易用:Stack提供了简单的接口和操作方法,使得使用起来非常便捷。
- 基于其他容器实现:Stack的底层实现通常基于deque或vector容器,保证了高效的插入和删除操作。
优缺点:
-
优点:
- 高效的插入和删除操作:Stack的插入和删除操作都是在栈顶进行,时间复杂度为常数时间。
- 线程安全:Stack在多线程环境下使用时,可以通过加锁等机制保证线程安全。
- 适用于各种后进先出场景:Stack适用于处理各种后进先出的数据流,如函数调用栈、表达式求值等。
-
缺点:
- 不支持随机访问:Stack不支持随机访问元素,只能在栈顶进行插入和删除操作。
- 不支持迭代器:Stack不支持迭代器,无法对栈中的元素进行遍历。
使用方法: 使用Stack容器非常简单,只需要包含头文件<stack>,然后通过创建Stack对象并调用其成员函数来进行操作。以下是一些常见的操作方法:
成员函数:
- 构造函数:用于创建一个空的栈。
- push():将元素压入栈顶。
- pop():将栈顶元素弹出栈。
- top():返回栈顶元素。
- empty():检查栈是否为空。
- size():返回栈中元素的个数。
适用场景:
- 函数调用栈:适用于需要按照函数调用顺序进行操作的场景,如递归算法、深度优先搜索等。
- 表达式求值:适用于需要按照表达式结构进行操作的场景,如中缀表达式转换为后缀表达式等。
- 堆栈操作:适用于需要按照堆栈数据结构进行操作的场景,如处理括号匹配、回文串判断等。
基本操作示例:
#include <iostream>
#include <stack>
#include <algorithm>
#include <numeric>
#include<vector>
int main() {
// 创建一个空栈
std::stack<int> myStack;
// 入栈操作
myStack.push(5);
myStack.push(10);
myStack.push(15);
// 使用循环遍历栈并打印元素
std::cout << "Stack elements: ";
std::stack<int> tempStack = myStack; // 复制一份栈
while (!tempStack.empty()) {
std::cout << tempStack.top() << " ";
tempStack.pop();
}
// 获取栈的大小并打印
std::cout << "Stack size: " << myStack.size() << std::endl;
// 判断栈是否为空
if (!myStack.empty()) {
// 访问栈顶元素并打印
std::cout << "Top element: " << myStack.top() << std::endl;
// 出栈操作
myStack.pop();
std::cout << "Popped top element" << std::endl;
}
std::cout << std::endl;
/// 使用排序算法对栈中的元素进行排序
std::vector<int> sortedVec;
while (!myStack.empty()) {
sortedVec.push_back(myStack.top());
myStack.pop();
}
std::sort(sortedVec.begin(), sortedVec.end());
// 使用循环遍历排序后的向量并将元素依次入栈
for (int i = sortedVec.size() - 1; i >= 0; --i) {
myStack.push(sortedVec[i]);
}
// 使用循环遍历栈并打印排序后的元素
std::cout << "Sorted stack elements: ";
std::stack<int> anotherStack = myStack; // 复制一份栈
while (!anotherStack.empty()) {
std::cout << anotherStack.top() << " ";
anotherStack.pop();
}
std::cout << std::endl;
// 查找最大/最小元素
int maxElement = sortedVec.back();
int minElement = sortedVec.front();
std::cout << "Max element in stack: " << maxElement << std::endl;
std::cout << "Min element in stack: " << minElement << std::endl;
return 0;
}
函数调用栈示例:
#include <iostream>
#include <stack>
//函数调用栈的示例
void func3() {
std::cout << "Inside func3" << std::endl;
}
void func2() {
std::cout << "Inside func2, calling func3" << std::endl;
}
void func1() {
std::cout << "Inside func1, calling func2" << std::endl;
}
int main() {
std::stack<void(*)()> callStack; // 使用函数指针作为栈元素类型
// 将所有函数指针存入栈中
callStack.push(func1);
callStack.push(func2);
callStack.push(func3);
// 依次调用栈中的函数
while (!callStack.empty()) {
// 取出栈顶函数指针
void (*currentFunc)() = callStack.top();
callStack.pop();
// 调用函数
currentFunc();
}
return 0;
}
表达式求值示例:
#include <iostream>
#include <stack>
#include <string>
//栈用来求表达式的值
// 函数用于计算后缀表达式的值
int evaluatePostfix(const std::string& expression) {
std::stack<int> operandStack; // 创建一个整数类型的栈用于存储操作数
// 遍历后缀表达式中的每个字符
for (char c : expression) {
if (std::isdigit(c)) { // 如果是数字字符,则将其转换为整数并压入栈中
operandStack.push(c - '0');
}
else if (c == '+') { // 如果是加号运算符,则从栈中弹出两个操作数相加,并将结果压入栈中
int operand2 = operandStack.top();
operandStack.pop();
int operand1 = operandStack.top();
operandStack.pop();
operandStack.push(operand1 + operand2);
}
}
// 返回栈顶元素,即为后缀表达式的值
return operandStack.top();
}
int main() {
std::string postfixExpression = "33+"; // 后缀表达式表示 3+3
std::cout << "Postfix Expression: " << postfixExpression << std::endl;
std::cout << "Result: " << evaluatePostfix(postfixExpression) << std::endl;
return 0;
}
堆栈操作:处理括号匹配、回文串判断示例:
#include <iostream>
#include <stack>
#include <string>
bool isMatchingParentheses(const std::string& expression) {
std::stack<char> parenthesesStack;
for (char ch : expression) {
if (ch == '(' || ch == '[' || ch == '{') {
parenthesesStack.push(ch);
}
else if (ch == ')' || ch == ']' || ch == '}') {
if (parenthesesStack.empty()) {
return false; // 括号不匹配,右括号多余
}
char top = parenthesesStack.top();
parenthesesStack.pop();
if ((ch == ')' && top != '(') || (ch == ']' && top != '[') || (ch == '}' && top != '{')) {
return false; // 括号不匹配,右括号与栈顶左括号不匹配
}
}
}
return parenthesesStack.empty(); // 括号匹配,堆栈应为空
}
// 判断字符串是否为回文串的函数
bool isPalindrome(const std::string& str) {
std::stack<char> charStack; // 创建一个字符栈
// 将字符串的字符依次压入栈中
for (char ch : str) {
charStack.push(ch);
}
// 逐个比较栈顶字符与字符串的字符
for (char ch : str) {
if (ch != charStack.top()) {
return false; // 如果有不相等的字符,则不是回文串
}
charStack.pop(); // 比较完毕后,弹出栈顶字符
}
return true; // 如果所有字符都匹配,则是回文串
}
int main() {
std::string expression1 = "(a+b)*[c-d]/{e+f}";
std::string expression2 = "((a+b)*[c-d]/{e+f}";
// 测试用例1:回文串
std::string str1 = "racecar";
// 测试用例2:非回文串
std::string str2 = "hello";
if (isMatchingParentheses(expression1)) {
std::cout << "表达式 1 有匹配的括号。" << std::endl;
}
else {
std::cout << "表达式 1 没有匹配的括号。" << std::endl;
}
if (isMatchingParentheses(expression2)) {
std::cout << "表达式 2 有匹配的括号。" << std::endl;
}
else {
std::cout << "表达式 2 没有匹配的括号。" << std::endl;
}
// 判断字符串1是否为回文串,并输出结果
if (isPalindrome(str1)) {
std::cout << str1 << " 是回文串。" << std::endl;
}
else {
std::cout << str1 << " 不是回文串。" << std::endl;
}
// 判断字符串2是否为回文串,并输出结果
if (isPalindrome(str2)) {
std::cout << str2 << " 是回文串。" << std::endl;
}
else {
std::cout << str2 << " 不是回文串。" << std::endl;
}
return 0;
}