从零开始:逐步学习使用C++ STL中的stack容器
引言
💡 作者简介:一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。技能涵盖了多个领域,包括C/C++、Linux、Nginx、MySQL、Redis、fastdfs、kafka、Docker、TCP/IP、协程、DPDK等。
👉
🎖️ CSDN实力新星、CSDN博客专家👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。👉
🔔 专栏地址:C++从零开始到精通👉
🔔 博客主页:https://blog.csdn.net/Long_xu
一、stack容器概述
stack是一种先进后出(First In Last OutFILO)的数据结构,它只有一个出口,形式如图所示。stack容器允许新增元素,移除元素,取得栈顶元素,但是除了最顶端外,没有任何其他方法可以存取stack的其他元素。换言之,stack不允许有遍历行为。有元素入栈的操作称为:push,将元素推出stack 的操作称为pop。
Stack所有元素的进出都必须符合"先进后出"的条件,只有stack顶端的元素,才有机会被外界取用。Stack不提供遍历功能,也不提供迭代器。
二、stack容器常用API
C++的stack
容器是通过<stack>
头文件提供的。
-
构造函数:
stack<T> s
:创建一个空的stack
,其中T
是数据类型。
-
成员函数:
push(const T& val)
:将元素val
压入栈顶。emplace(Args&&... args)
:通过参数构造一个元素并将其压入栈顶。pop()
:移除栈顶元素。top()
:返回栈顶元素的引用。empty()
:检查栈是否为空,返回布尔值。size()
:返回栈中元素的个数。
-
非成员函数:
swap(stack<T>& other)
:交换两个栈的内容。
stack
不提供遍历功能,因为它是一种后进先出(LIFO)数据结构。
2.1、构造函数
stack
容器的构造函数原型如下:
cpp
explicit stack(const Container& cont = Container());
其中,Container
是可选参数,用于指定底层容器类型,默认为deque
。
以下是几个使用示例:
示例 1:使用默认构造函数创建空的stack
cpp
#include <iostream>
#include <stack>
int main() {
std::stack<int> s; // 默认构造函数创建一个空的stack
if (s.empty()) {
std::cout << "Stack is empty!" << std::endl;
}
return 0;
}
示例 2:使用vector
作为底层容器创建stack
cpp
#include <iostream>
#include <stack>
#include <vector>
int main() {
std::stack<int, std::vector<int>> s; // 使用vector作为底层容器
s.push(10);
s.push(20);
s.push(30);
while (!s.empty()) {
std::cout << s.top() << " "; // 输出栈顶元素
s.pop(); // 弹出栈顶元素
}
return 0;
}
示例 3:使用现有容器初始化stack
cpp
#include <iostream>
#include <stack>
#include <list>
int main() {
std::list<int> values = {1, 2, 3, 4};
std::stack<int, std::list<int>> s(values); // 使用现有容器初始化stack
while (!s.empty()) {
std::cout << s.top() << " "; // 输出栈顶元素
s.pop(); // 弹出栈顶元素
}
return 0;
}
这些示例展示了如何使用stack
容器的构造函数来创建空的栈或从现有容器初始化栈。可以根据需要选择不同的底层容器类型,如默认的deque
或用户指定的vector
、list
等。
2.2、赋值操作
可以使用std::stack
模板类中的成员函数swap()
来交换两个栈的内容实现赋值的效果。
swap()
函数的原型如下:
cpp
void swap(stack& other);
使用示例:
cpp
#include <iostream>
#include <stack>
int main() {
std::stack<int> stack1;
std::stack<int> stack2;
stack1.push(1);
stack1.push(2);
stack1.push(3);
stack2.push(4);
stack2.push(5);
std::cout << "Stack 1: ";
while (!stack1.empty()) {
std::cout << stack1.top() << " "; // 输出栈1的元素
stack1.pop();
}
std::cout << "\nStack 2: ";
while (!stack2.empty()) {
std::cout << stack2.top() << " "; // 输出栈2的元素
stack2.pop();
}
stack1.swap(stack2); // 交换栈1和栈2的内容
std::cout << "\nStack 1 after swapping: ";
while (!stack1.empty()) {
std::cout << stack1.top() << " "; // 输出交换后的栈1的元素
stack1.pop();
}
std::cout << "\nStack 2 after swapping: ";
while (!stack2.empty()) {
std::cout << stack2.top() << " "; // 输出交换后的栈2的元素
stack2.pop();
}
return 0;
}
输出:
bash
Stack 1: 3 2 1
Stack 2: 5 4
Stack 1 after swapping: 5 4
Stack 2 after swapping: 3 2 1
以上示例中,通过调用swap()
函数来交换了两个栈stack1
和stack2
的内容。这样就实现了将一个栈的元素赋值给另一个栈的效果。
2.3、数据存取操作
std::stack
容器的数据存取操作函数包括:
top()
:返回栈顶元素的引用,但不会删除该元素。push(const T& value)
:将元素插入到栈顶。pop()
:移除栈顶元素,没有返回值。
使用示例:
cpp
#include <iostream>
#include <stack>
int main() {
std::stack<int> stack;
stack.push(1);
stack.push(2);
stack.push(3);
// 访问栈顶元素
int topElement = stack.top();
std::cout << "Top element: " << topElement << std::endl;
// 修改栈顶元素
stack.top() = 4;
// 移除栈顶元素
stack.pop();
std::cout << "Stack elements:";
while (!stack.empty()) {
std::cout << " " << stack.top();
stack.pop();
}
std::cout << std::endl;
return 0;
}
输出:
bash
Top element: 3
Stack elements: 2 1
2.4、大小操作
std::stack
容器提供了以下函数来进行大小操作:
empty()
:返回栈是否为空,如果栈为空则返回true
,否则返回false
。size()
:返回栈中元素的数量。
以下是这些函数的函数原型和使用示例:
cpp
#include <iostream>
#include <stack>
int main() {
std::stack<int> stack;
stack.push(1);
stack.push(2);
stack.push(3);
bool isEmpty = stack.empty();
std::cout << "Is stack empty? " << (isEmpty ? "Yes" : "No") << std::endl;
size_t stackSize = stack.size();
std::cout << "Stack size: " << stackSize << std::endl;
return 0;
}
输出:
bash
Is stack empty? No
Stack size: 3
三、使用stack容器实现一个高效的算法
使用C++的stack
容器实现简单算法,该算法用于判断一个字符串中的括号是否匹配。
cpp
#include <iostream>
#include <stack>
#include <string>
bool isBracketMatching(const std::string& str) {
std::stack<char> brackets;
for (char ch : str) {
if (ch == '(' || ch == '[' || ch == '{') {
brackets.push(ch);
} else if (ch == ')' || ch == ']' || ch == '}') {
// 如果当前字符为右括号
if (brackets.empty()) {
// 栈为空,无法匹配
return false;
} else {
char top = brackets.top();
brackets.pop();
// 判断栈顶元素与当前右括号是否匹配
if ((top == '(' && ch != ')') ||
(top == '[' && ch != ']') ||
(top == '{' && ch != '}')) {
return false;
}
}
}
}
// 所有字符遍历完成后,栈为空才说明括号全部匹配
return brackets.empty();
}
int main() {
std::string str1 = "({})[]"; // 匹配
std::string str2 = "{[}]"; // 不匹配
std::cout << "字符串1括号" << (isBracketMatching(str1) ? "匹配" : "不匹配") << std::endl;
std::cout << "字符串2括号" << (isBracketMatching(str2) ? "匹配" : "不匹配") << std::endl;
return 0;
}
首先,我们遍历字符串中的每个字符,如果遇到左括号('('
、'['
或'{'
),我们将其压入栈中。当遇到右括号时,我们检查栈顶元素是否与当前右括号匹配,并将栈顶元素弹出。如果任何时刻栈为空、栈顶元素与当前右括号不匹配,或者遍历结束后栈仍然非空,那么就意味着括号不匹配。
在main()
函数中,我们测试了两个字符串的括号匹配情况,并输出相应的结果。
运行上述代码,输出:
bash
字符串1括号匹配
字符串2括号不匹配
示例演示了如何利用C++的stack
容器来实现一个简单算法,通过使用栈来追踪括号的嵌套关系,并判断括号是否匹配。这只是stack
容器的一个简单应用示例,而stack
还有其他更多有用的功能可以探索和利用。
总结
深入讲解了C++ STL中的stack
容器的基本概念和操作。首先介绍了栈的定义和特点,然后详细解释了stack
容器的创建和管理方法,包括入栈、出栈和访问栈顶元素等操作。此外,还重点探讨了stack
容器的大小操作函数,并通过实例加深了对其用法的理解。通过本文的学习,读者能够全面了解如何在C++中运用stack
来实现栈结构,并且能够合理地利用stack
提高代码效率和可读性。无论读者是初学者还是有一定经验的开发者,本文都能帮助他们掌握使用C++ STL中的stack
容器的技巧和技能,为日后的编程工作打下坚实的基础。