1/*
2 * STL Containers and Algorithms Demo
3 *
4 * Demonstrates:
5 * - vector, map, unordered_map, set
6 * - Range-based for loops
7 * - STL algorithms: sort, transform, accumulate, find_if
8 * - std::ranges (C++20)
9 * - Lambda expressions with STL
10 *
11 * Compile: g++ -std=c++20 -Wall -Wextra 02_stl_containers.cpp -o stl_containers
12 */
13
14#include <iostream>
15#include <vector>
16#include <map>
17#include <unordered_map>
18#include <set>
19#include <algorithm>
20#include <numeric>
21#include <string>
22#include <ranges>
23
24// ============ std::vector ============
25void demo_vector() {
26 std::cout << "\n=== std::vector ===\n";
27
28 std::vector<int> nums = {5, 2, 8, 1, 9};
29
30 // Range-based for loop
31 std::cout << "Original: ";
32 for (const auto& n : nums) {
33 std::cout << n << " ";
34 }
35 std::cout << "\n";
36
37 // Push back
38 nums.push_back(42);
39 std::cout << "After push_back(42): size=" << nums.size() << "\n";
40
41 // Sort
42 std::sort(nums.begin(), nums.end());
43 std::cout << "Sorted: ";
44 for (const auto& n : nums) {
45 std::cout << n << " ";
46 }
47 std::cout << "\n";
48
49 // Erase
50 nums.erase(nums.begin() + 2); // Remove 3rd element
51 std::cout << "After erase(index 2): ";
52 for (const auto& n : nums) {
53 std::cout << n << " ";
54 }
55 std::cout << "\n";
56}
57
58// ============ std::map (ordered) ============
59void demo_map() {
60 std::cout << "\n=== std::map ===\n";
61
62 std::map<std::string, int> scores;
63 scores["Alice"] = 95;
64 scores["Bob"] = 87;
65 scores["Charlie"] = 92;
66
67 // Iterate (ordered by key)
68 std::cout << "Scores (sorted by name):\n";
69 for (const auto& [name, score] : scores) {
70 std::cout << " " << name << ": " << score << "\n";
71 }
72
73 // Find
74 if (scores.find("Bob") != scores.end()) {
75 std::cout << "Bob's score: " << scores["Bob"] << "\n";
76 }
77
78 // Insert or update
79 scores.insert_or_assign("Alice", 98);
80 std::cout << "Updated Alice's score: " << scores["Alice"] << "\n";
81}
82
83// ============ std::unordered_map (hash table) ============
84void demo_unordered_map() {
85 std::cout << "\n=== std::unordered_map ===\n";
86
87 std::unordered_map<std::string, int> word_count;
88 std::vector<std::string> words = {"apple", "banana", "apple", "cherry", "banana", "apple"};
89
90 for (const auto& word : words) {
91 word_count[word]++;
92 }
93
94 std::cout << "Word frequencies:\n";
95 for (const auto& [word, count] : word_count) {
96 std::cout << " " << word << ": " << count << "\n";
97 }
98}
99
100// ============ std::set ============
101void demo_set() {
102 std::cout << "\n=== std::set ===\n";
103
104 std::set<int> unique_nums = {5, 2, 8, 2, 1, 5, 9};
105
106 std::cout << "Unique numbers (sorted): ";
107 for (const auto& n : unique_nums) {
108 std::cout << n << " ";
109 }
110 std::cout << "\n";
111
112 // Insert
113 auto [it, inserted] = unique_nums.insert(3);
114 std::cout << "Insert 3: " << (inserted ? "success" : "already exists") << "\n";
115
116 auto [it2, inserted2] = unique_nums.insert(5);
117 std::cout << "Insert 5: " << (inserted2 ? "success" : "already exists") << "\n";
118
119 // Contains (C++20)
120 std::cout << "Contains 8: " << unique_nums.contains(8) << "\n";
121 std::cout << "Contains 100: " << unique_nums.contains(100) << "\n";
122}
123
124// ============ STL Algorithms ============
125void demo_algorithms() {
126 std::cout << "\n=== STL Algorithms ===\n";
127
128 std::vector<int> nums = {1, 2, 3, 4, 5};
129
130 // std::transform with lambda
131 std::vector<int> squared;
132 std::transform(nums.begin(), nums.end(), std::back_inserter(squared),
133 [](int x) { return x * x; });
134
135 std::cout << "Squared: ";
136 for (const auto& n : squared) {
137 std::cout << n << " ";
138 }
139 std::cout << "\n";
140
141 // std::accumulate (sum)
142 int sum = std::accumulate(nums.begin(), nums.end(), 0);
143 std::cout << "Sum: " << sum << "\n";
144
145 // std::accumulate (product)
146 int product = std::accumulate(nums.begin(), nums.end(), 1, std::multiplies<int>());
147 std::cout << "Product: " << product << "\n";
148
149 // std::find_if with lambda
150 auto it = std::find_if(nums.begin(), nums.end(), [](int x) { return x > 3; });
151 if (it != nums.end()) {
152 std::cout << "First element > 3: " << *it << "\n";
153 }
154
155 // std::count_if
156 int count_even = std::count_if(nums.begin(), nums.end(), [](int x) { return x % 2 == 0; });
157 std::cout << "Count even numbers: " << count_even << "\n";
158
159 // std::all_of, std::any_of, std::none_of
160 bool all_positive = std::all_of(nums.begin(), nums.end(), [](int x) { return x > 0; });
161 std::cout << "All positive: " << all_positive << "\n";
162}
163
164// ============ std::ranges (C++20) ============
165void demo_ranges() {
166 std::cout << "\n=== std::ranges (C++20) ===\n";
167
168 std::vector<int> nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
169
170 // Filter and transform using views
171 auto even_squared = nums
172 | std::views::filter([](int x) { return x % 2 == 0; })
173 | std::views::transform([](int x) { return x * x; });
174
175 std::cout << "Even numbers squared: ";
176 for (const auto& n : even_squared) {
177 std::cout << n << " ";
178 }
179 std::cout << "\n";
180
181 // Take first 5 elements
182 auto first_five = nums | std::views::take(5);
183 std::cout << "First 5: ";
184 for (const auto& n : first_five) {
185 std::cout << n << " ";
186 }
187 std::cout << "\n";
188
189 // Drop first 5, take next 3
190 auto middle = nums | std::views::drop(5) | std::views::take(3);
191 std::cout << "Middle (drop 5, take 3): ";
192 for (const auto& n : middle) {
193 std::cout << n << " ";
194 }
195 std::cout << "\n";
196
197 // Reverse view
198 auto reversed = nums | std::views::reverse;
199 std::cout << "Reversed: ";
200 for (const auto& n : reversed) {
201 std::cout << n << " ";
202 }
203 std::cout << "\n";
204}
205
206// ============ Lambda Expressions ============
207void demo_lambdas() {
208 std::cout << "\n=== Lambda Expressions ===\n";
209
210 // Basic lambda
211 auto add = [](int a, int b) { return a + b; };
212 std::cout << "add(3, 4) = " << add(3, 4) << "\n";
213
214 // Capture by value
215 int x = 10;
216 auto add_x = [x](int y) { return x + y; };
217 std::cout << "add_x(5) = " << add_x(5) << "\n";
218
219 // Capture by reference
220 int count = 0;
221 auto increment = [&count]() { count++; };
222 increment();
223 increment();
224 std::cout << "Count after 2 increments: " << count << "\n";
225
226 // Generic lambda (C++14)
227 auto print = [](const auto& value) {
228 std::cout << "Value: " << value << "\n";
229 };
230 print(42);
231 print(3.14);
232 print("hello");
233}
234
235// ============ Main ============
236int main() {
237 std::cout << "STL Containers and Algorithms Demo\n";
238 std::cout << "===================================\n";
239
240 demo_vector();
241 demo_map();
242 demo_unordered_map();
243 demo_set();
244 demo_algorithms();
245 demo_ranges();
246 demo_lambdas();
247
248 std::cout << "\nAll demos completed!\n";
249 return 0;
250}