In this tutorial, we will delve into the Stack data structure using the Standard Template Library (STL) in C++. A stack is a fundamental linear data structure that follows the Last-In-First-Out (LIFO) principle. This means that the last element added to the stack will be the first one to be removed. Stacks are widely used in various applications, including expression evaluation, function call management, and undo mechanisms.
A stack is a linear data structure where elements are added or removed from only one end, known as the top. This makes stacks ideal for scenarios where you need to process items in the reverse order of their arrival. The primary operations associated with a stack are:
Understanding these operations and their implementations will help you effectively use stacks in your C++ programs. Let's explore each operation with code examples.
The push operation adds an element to the top of the stack. Here’s how you can implement it using the STL stack container:
1#include <iostream>2#include <stack>34int main() {5std::stack<int> myStack;6myStack.push(10);7myStack.push(20);8myStack.push(30);910while (!myStack.empty()) {11std::cout << "Top element: " << myStack.top() << std::endl;12myStack.pop();13}1415return 0;16}
Top element: 30 Top element: 20 Top element: 10
The pop operation removes the top element from the stack. In the previous example, we used a loop to pop all elements until the stack is empty.
1#include <iostream>2#include <stack>34int main() {5std::stack<int> myStack;6myStack.push(10);7myStack.push(20);8myStack.push(30);910while (!myStack.empty()) {11std::cout << "Popped element: " << myStack.top() << std::endl;12myStack.pop();13}1415return 0;16}
Popped element: 30 Popped element: 20 Popped element: 10
The top operation retrieves the top element without removing it from the stack.
1#include <iostream>2#include <stack>34int main() {5std::stack<int> myStack;6myStack.push(10);7myStack.push(20);8myStack.push(30);910std::cout << "Top element: " << myStack.top() << std::endl;1112return 0;13}
Top element: 30
The empty operation checks if the stack is empty.
1#include <iostream>2#include <stack>34int main() {5std::stack<int> myStack;6std::cout << "Is stack empty? " << (myStack.empty() ? "Yes" : "No") << std::endl;78myStack.push(10);9std::cout << "After pushing an element, is stack empty? " << (myStack.empty() ? "Yes" : "No") << std::endl;1011return 0;12}
Is stack empty? Yes After pushing an element, is stack empty? No
The size operation returns the number of elements in the stack.
1#include <iostream>2#include <stack>34int main() {5std::stack<int> myStack;6std::cout << "Size of stack: " << myStack.size() << std::endl;78myStack.push(10);9myStack.push(20);10std::cout << "After pushing two elements, size of stack: " << myStack.size() << std::endl;1112return 0;13}
Size of stack: 0 After pushing two elements, size of stack: 2
One common application of stacks is bracket matching in expressions. You can use a stack to ensure that every opening bracket has a corresponding closing bracket.
1#include <iostream>2#include <stack>3#include <string>45bool areBracketsBalanced(const std::string& expression) {6std::stack<char> bracketStack;7for (char ch : expression) {8if (ch == '(' || ch == '{' || ch == '[') {9bracketStack.push(ch);10} else if (ch == ')' || ch == '}' || ch == ']') {11if (bracketStack.empty()) {12return false;13}14char top = bracketStack.top();15bracketStack.pop();16if ((ch == ')' && top != '(') ||17(ch == '}' && top != '{') ||18(ch == ']' && top != '[')) {19return false;20}21}22}23return bracketStack.empty();24}2526int main() {27std::string expression = "{[()]}";28if (areBracketsBalanced(expression)) {29std::cout << "Brackets are balanced." << std::endl;30} else {31std::cout << "Brackets are not balanced." << std::endl;32}3334return 0;35}
Brackets are balanced.
Stacks can be used to implement an undo mechanism in applications like text editors or painting software.
1#include <iostream>2#include <stack>3#include <string>45class TextEditor {6private:7std::stack<std::string> history;8std::string currentText;910public:11void type(const std::string& text) {12history.push(currentText);13currentText += text;14}1516void undo() {17if (!history.empty()) {18currentText = history.top();19history.pop();20}21}2223std::string getCurrentText() const {24return currentText;25}26};2728int main() {29TextEditor editor;30editor.type("Hello");31editor.type(", World!");32std::cout << "Current text: " << editor.getCurrentText() << std::endl;3334editor.undo();35std::cout << "After undo: " << editor.getCurrentText() << std::endl;3637return 0;38}
Current text: Hello, World! After undo: Hello
| Operation | Description |
|---|---|
push | Adds an element to the top of the stack. |
pop | Removes the top element from the stack. |
top | Retrieves the top element without removing it. |
empty | Checks if the stack is empty. |
size | Returns the number of elements in the stack. |
Key takeaways:
stack container that simplifies stack operations.In the next tutorial, we will explore another fundamental data structure: Queue. Queues differ from stacks in their operation order (FIFO vs LIFO) and have various applications such as scheduling tasks and breadth-first search algorithms. Stay tuned!