Vectors–>
- Definition, Size&Capacity, Push_Back, Pop_Back,
- Front, Back, at,Clear, Empty, Resize, Swap,
- Sort, reverse, begin & end
- Vector as Stack, Queue & LinkedList using C++ STL
- Nested STL (Standard Template Library)
MAP–>
- C++ STL (Standard Template Library) is a part of the C++ Standard Library that provides a collection of template classes and functions to facilitate efficient programming. It includes containers (such as
vector
,list
,deque
,map
, andset
) that store and manage data, algorithms (likesort()
,find()
,reverse()
) to perform operations on containers, and iterators for traversing through containers (e.g.,begin()
,end()
). STL also offers function objects (e.g.,greater()
,less()
) that can be used like functions. The use of templates makes the STL highly generic and reusable, enabling developers to work with different data types without writing custom solutions, promoting efficiency, and reducing development time.
Let’s discuss the C++ vector tutorial with examples:
Vector Definition and Declaration
This example shows how to declare and initialize a vector in various ways:
#include <iostream>
#include <vector>
using namespace std;
int main() {
// Create an empty vector
vector<int> v;
// Create a vector with 5 elements, initialized to 10
vector<int> v2(5, 10);
// Create a vector initialized with a list of values
vector<int> v3 = {1, 2, 3, 4, 5};
// Output the values of v3
cout << "Vector v3: ";
for (int i : v3) {
cout << i << " ";
}
cout << endl;
return 0;
}
Output:
Vector v3: 1 2 3 4 5
Vector Size and Capacity
This example demonstrates the difference between size()
and capacity()
.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// Size of the vector
cout << "Size: " << v.size() << endl; // Output: 5
// Capacity of the vector
cout << "Capacity: " << v.capacity() << endl; // Output may vary, likely 8 or 10
return 0;
}
Example Output:
Size: 5
Capacity: 8
Note: The capacity may vary depending on the implementation, but typically it will be more than or equal to the size. In this case, the
capacity()
might return8
because the vector can grow beyond the current number of elements.
Push Back and Pop Back
This example shows how to add and remove elements from the vector using push_back()
and pop_back()
.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v;
// Push elements to the vector
v.push_back(10);
v.push_back(20);
v.push_back(30);
cout << "Vector after push_back operations: ";
for (int i : v) {
cout << i << " ";
}
cout << endl;
// Pop an element from the vector
v.pop_back();
cout << "Vector after pop_back operation: ";
for (int i : v) {
cout << i << " ";
}
cout << endl;
return 0;
}
Output:
Vector after push_back operations: 10 20 30
Vector after pop_back operation: 10 20
Accessing Elements: front()
, back()
, and at()
This example demonstrates how to access the first, last, and specific elements using front()
, back()
, and at()
.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {10, 20, 30, 40, 50};
// Accessing the first and last elements
cout << "First element: " << v.front() << endl; // Output: 10
cout << "Last element: " << v.back() << endl; // Output: 50
// Accessing an element using at()
cout << "Element at index 2: " << v.at(2) << endl; // Output: 30
try {
// Trying to access an out-of-bounds element
cout << v.at(10) << endl; // Will throw out_of_range exception
} catch (const out_of_range& e) {
cout << "Exception: " << e.what() << endl; // Output: out_of_range exception
}
return 0;
}
Output:
First element: 10
Last element: 50
Element at index 2: 30
Exception: out_of_range
Other Useful Functions
clear()
– Removes all elements in the vector.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
// Clear the vector
v.clear();
cout << "Vector size after clear: " << v.size() << endl; // Output: 0
return 0;
}
Output:
Vector size after clear: 0
empty()
– Checks if the vector is empty.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3};
cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << endl; // Output: No
v.clear();
cout << "Is vector empty? " << (v.empty() ? "Yes" : "No") << endl; // Output: Yes
return 0;
}
Output:
Is vector empty? No
Is vector empty? Yes
resize()
– Resizes the vector to a given number of elements.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v = {1, 2, 3};
// Resize the vector to hold 5 elements
v.resize(5);
cout << "Vector after resizing: ";
for (int i : v) {
cout << i << " ";
}
cout << endl; // Output: 1 2 3 0 0
return 0;
}
Output:
Vector after resizing: 1 2 3 0 0
swap() - Swaps the contents of two vectors.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v1 = {1, 2, 3};
vector<int> v2 = {4, 5, 6};
// Swap v1 and v2
v1.swap(v2);
cout << "Vector v1 after swap: ";
for (int i : v1) {
cout << i << " ";
}
cout << endl; // Output: 4 5 6
cout << "Vector v2 after swap: ";
for (int i : v2) {
cout << i << " ";
}
cout << endl; // Output: 1 2 3
return 0;
}
Output:
Vector v1 after swap: 4 5 6
Vector v2 after swap: 1 2 3
Sort, reverse, begin & end
#include <iostream>
#include <vector>
#include <algorithm> // for sort, reverse
#include <functional> // for greater
using namespace std;
int main() {
// 1. Containers: Create a vector
vector<int> v = {3, 1, 2, 5, 4};
// 2. Algorithms: Sort the vector in descending order using a function object
sort(v.begin(), v.end(), greater<int>());
// 3. Iterators: Traverse the vector using an iterator
cout << "Sorted vector: ";
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // Output: 5 4 3 2 1
}
cout << endl;
// 4. Algorithms: Reverse the vector
reverse(v.begin(), v.end());
// 5. Iterators: Traverse again using an iterator
cout << "Reversed vector: ";
for (auto it = v.begin(); it != v.end(); ++it) {
cout << *it << " "; // Output: 1 2 3 4 5
}
cout << endl;
return 0;
}
Summary
vector
is a sequence container in C++ that dynamically resizes as elements are added or removed.size()
gives the current number of elements, whilecapacity()
indicates how much memory has been allocated internally.push_back()
adds an element to the end of the vector, whilepop_back()
removes the last element.front()
,back()
, andat()
are used to access the first, last, and specific elements in the vector.clear()
,empty()
,resize()
, andswap()
are other useful functions for manipulating the vector.
These functions form the foundation for working with vectors in C++ STL.
Vector as Stack, Queue & LinkedList using C++ STL
Here’s a short explanation with examples for using vector as a stack, queue, and linked list using C++ STL:
Vector as a Stack
A stack follows the LIFO (Last In First Out) principle. You can use push_back()
to add elements and pop_back()
to remove them.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> stack;
// Push elements onto the stack
stack.push_back(10);
stack.push_back(20);
stack.push_back(30);
// Pop an element from the stack
stack.pop_back();
// Print the stack
for (int i : stack) {
cout << i << " "; // Output: 10 20
}
cout << endl;
return 0;
}
Queue Using STL (queue
container)
A queue follows the FIFO (First In First Out) principle. You can use push()
to add elements and pop()
to remove them.
#include <iostream>
#include <queue>
using namespace std;
int main() {
queue<int> q;
// Enqueue elements
q.push(10);
q.push(20);
q.push(30);
// Dequeue an element
q.pop();
// Print the front element of the queue
cout << "Front: " << q.front() << endl; // Output: 20
// Print the queue size
cout << "Size: " << q.size() << endl; // Output: 2
return 0;
}
Linked List Using STL (list
container)
A linked list allows efficient insertion and removal at both ends. You can use push_back()
, push_front()
, pop_back()
, pop_front()
, and insert()
.
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> l;
// Insert elements at the back
l.push_back(10);
l.push_back(20);
// Insert element at the front
l.push_front(5);
// Remove element from the front
l.pop_front();
// Remove element from the back
l.pop_back();
// Print the linked list
for (int i : l) {
cout << i << " "; // Output: 10
}
cout << endl;
return 0;
}
Summary of Functions:
- Stack (using vector):
push_back()
: Add element to the stackpop_back()
: Remove element from the stack
- Queue (using
queue
container):push()
: Add element to the queuepop()
: Remove element from the queuefront()
: Access the front elementback()
: Access the back elementsize()
: Get the size of the queue
- Linked List (using
list
container):push_back()
: Add element to the endpush_front()
: Add element to the frontpop_back()
: Remove element from the endpop_front()
: Remove element from the frontinsert()
: Insert element at a specific position
Nested STL
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <unordered_map>
int main() {
// 1. Vector of Vectors: Used to represent a 2D matrix or grid.
std::vector<std::vector<int>> matrix = { // Declaring a vector where each element is another vector.
{1, 2, 3}, // First row of the matrix.
{4, 5, 6}, // Second row of the matrix.
{7, 8, 9} // Third row of the matrix.
};
std::cout << "Vector of Vectors:" << std::endl;
for (const auto& row : matrix) { // Loop through each row (a vector) in the matrix.
for (int value : row) { // Loop through each value in the current row.
std::cout << value << " "; // Print the value followed by a space.
}
std::cout << std::endl; // Print a newline after each row.
}
// 2. Set of Pairs: Used to store unique pairs of integers, useful for coordinate-like data.
std::set<std::pair<int, int>> points = {{1, 2}, {3, 4}, {5, 6}}; // Declare a set of pairs and initialize it with some values.
std::cout << "\nSet of Pairs:" << std::endl;
for (const auto& point : points) { // Loop through each pair in the set.
std::cout << "(" << point.first << ", " << point.second << ")" << std::endl; // Access and print the pair using `first` and `second`.
}
// 3. Map of Sets: Used to group unique elements (sets) under specific keys.
std::map<std::string, std::set<int>> studentSubjects; // Declare a map where keys are strings and values are sets of integers.
studentSubjects["Alice"] = {101, 102, 103}; // Assign a set of subject codes to "Alice".
studentSubjects["Bob"] = {102, 104}; // Assign a set of subject codes to "Bob".
std::cout << "\nMap of Sets:" << std::endl;
for (const auto& pair : studentSubjects) { // Loop through each key-value pair in the map.
std::cout << pair.first << ": "; // Print the key (student name).
for (int subject : pair.second) { // Loop through the set of subject codes.
std::cout << subject << " "; // Print each subject code.
}
std::cout << std::endl; // Print a newline after each student's subjects.
}
// 4. Map of Vectors: Used to store lists of values (vectors) under each key.
std::map<std::string, std::vector<int>> studentScores; // Declare a map where keys are strings and values are vectors of integers.
studentScores["Alice"] = {90, 85, 88}; // Assign a vector of scores to "Alice".
studentScores["Bob"] = {78, 82}; // Assign a vector of scores to "Bob".
std::cout << "\nMap of Vectors:" << std::endl;
for (const auto& pair : studentScores) { // Loop through each key-value pair in the map.
std::cout << pair.first << ": "; // Print the key (student name).
for (int score : pair.second) { // Loop through the vector of scores.
std::cout << score << " "; // Print each score.
}
std::cout << std::endl; // Print a newline after each student's scores.
}
// 5. Unordered Map of Unordered Sets: Used to represent fast lookups, such as a graph adjacency list.
std::unordered_map<int, std::unordered_set<int>> graph; // Declare an unordered map where keys are integers and values are unordered sets of integers.
graph[1] = {2, 3}; // Add edges from node 1 to nodes 2 and 3.
graph[2] = {1, 4}; // Add edges from node 2 to nodes 1 and 4.
std::cout << "\nUnordered Map of Unordered Sets (Graph Representation):" << std::endl;
for (const auto& pair : graph) { // Loop through each key-value pair in the map.
std::cout << pair.first << " -> "; // Print the key (a node in the graph).
for (int neighbor : pair.second) { // Loop through the set of neighbors.
std::cout << neighbor << " "; // Print each neighbor.
}
std::cout << std::endl; // Print a newline after each node's neighbors.
}
return 0; // Indicate successful execution.
}
C++ STL map
Tutorial
Introduction
In C++, the Standard Template Library (STL) provides several useful container classes, and one of the most commonly used is the map
. A map
is an associative container that stores key-value pairs. It is similar to a dictionary or hash table in other programming languages.
Key Properties of a map
:
- Associative: Elements in a
map
are stored as key-value pairs. - Unique Keys: Each key in the
map
must be unique. If you try to insert a duplicate key, it will overwrite the existing value. - Ordered: The elements in the
map
are always stored in a sorted order based on the key. The default sorting is in ascending order, but this can be customized.
Syntax:
#include <map>
// Declaration of a map
map<KeyType, ValueType> mapName;
Where:
KeyType
: Type of the key (e.g.,int
,string
).ValueType
: Type of the value associated with the key.
1. Basic Operations on map
1.1 Creating a map
A map
can be created by specifying the key type and value type. Here’s an example:
map<int, string> studentGrades;
This creates a map where the key is of type int
(e.g., student ID) and the value is of type string
(e.g., grade).
1.2 Inserting Elements into a map
There are two ways to insert elements into a map:
Using operator[]
:
studentGrades[101] = "A"; // Inserting key-value pair (101, "A")
studentGrades[102] = "B"; // Inserting key-value pair (102, "B")
Using insert()
method:
studentGrades.insert({103, "C"}); // Inserting using a pair
studentGrades.insert(make_pair(104, "A"));
1.3 Accessing Elements
You can access values in a map
by using the key:
cout << studentGrades[101] << endl; // Output: A
Note that if the key does not exist, the operator[]
will insert a default value. To check if a key exists before accessing, use find()
:
if (studentGrades.find(105) != studentGrades.end()) {
cout << studentGrades[105] << endl;
} else {
cout << "Key not found!" << endl;
}
1.4 Size of a map
The size of a map
(number of elements) can be obtained using the size()
method:
cout << "Size of map: " << studentGrades.size() << endl;
1.5 Erasing Elements
You can remove elements using the erase()
function:
studentGrades.erase(101); // Removes the element with key 101
You can also remove elements using iterators:
auto it = studentGrades.find(102);
if (it != studentGrades.end()) {
studentGrades.erase(it);
}
2. Iterating Over a map
2.1 Using Iterator
To iterate over a map
, you can use an iterator:
for (auto it = studentGrades.begin(); it != studentGrades.end(); ++it) {
cout << "ID: " << it->first << ", Grade: " << it->second << endl;
}
2.2 Using Range-based For Loop
Since C++11, you can also use a range-based for loop for simpler iteration:
for (const auto& entry : studentGrades) {
cout << "ID: " << entry.first << ", Grade: " << entry.second << endl;
}
2.3 Reverse Iteration
To iterate in reverse order, you can use rbegin()
and rend()
:
for (auto it = studentGrades.rbegin(); it != studentGrades.rend(); ++it) {
cout << "ID: " << it->first << ", Grade: " << it->second << endl;
}
3. Advanced map
Topics
3.1 Custom Sorting (Comparators)
By default, map
sorts its keys in ascending order. However, you can provide a custom comparator to change the sorting order.
Example: Sorting in descending order
map<int, string, greater<int>> reverseStudentGrades;
reverseStudentGrades[101] = "A";
reverseStudentGrades[102] = "B";
reverseStudentGrades[103] = "A";
for (const auto& entry : reverseStudentGrades) {
cout << "ID: " << entry.first << ", Grade: " << entry.second << endl;
}
3.2 multimap
A multimap
allows multiple elements with the same key, unlike map
where each key is unique. This is useful when you need to store multiple values under the same key.
Example:
multimap<int, string> studentSubjects;
studentSubjects.insert({101, "Math"});
studentSubjects.insert({101, "Physics"});
studentSubjects.insert({102, "Chemistry"});
for (const auto& entry : studentSubjects) {
cout << "ID: " << entry.first << ", Subject: " << entry.second << endl;
}
3.3 map
with Complex Types (Custom Classes)
You can use custom types (classes or structs) as keys in a map
. To do so, you need to define how the keys should be compared (usually by overloading the <
operator).
Example with a custom comparator:
struct Student {
int id;
string name;
// Overload the < operator for comparison
bool operator<(const Student& other) const {
return id < other.id;
}
};
map<Student, string> studentInfo;
studentInfo[Student{101, "John"}] = "A";
studentInfo[Student{102, "Jane"}] = "B";
for (const auto& entry : studentInfo) {
cout << "ID: " << entry.first.id << ", Name: " << entry.first.name << ", Grade: " << entry.second << endl;
}
3.4 Performance Considerations
- Time Complexity:
- Insertion, deletion, and lookup operations all take O(log n) time because
map
is implemented as a balanced binary search tree (typically Red-Black Tree).
- Insertion, deletion, and lookup operations all take O(log n) time because
- Space Complexity:
- The space complexity of a
map
is O(n), wheren
is the number of elements stored in the map.
- The space complexity of a
4. Example: Complete Code of Using map
#include <iostream>
#include <map>
using namespace std;
int main() {
// 1. Creating a map
map<int, string> studentGrades;
// 2. Inserting elements
studentGrades[101] = "A";
studentGrades[102] = "B";
studentGrades.insert({103, "C"});
// 3. Accessing elements
cout << "Grade of student with ID 101: " << studentGrades[101] << endl;
// 4. Iterating over the map
cout << "All student grades:\n";
for (const auto& entry : studentGrades) {
cout << "ID: " << entry.first << ", Grade: " << entry.second << endl;
}
// 5. Using custom comparator for reverse sorting
map<int, string, greater<int>> reverseMap;
reverseMap[101] = "A";
reverseMap[102] = "B";
reverseMap[103] = "C";
cout << "Reverse sorted map:\n";
for (const auto& entry : reverseMap) {
cout << "ID: " << entry.first << ", Grade: " << entry.second << endl;
}
return 0;
}
Output:
Grade of student with ID 101: A
All student grades:
ID: 101, Grade: A
ID: 102, Grade: B
ID: 103, Grade: C
Reverse sorted map:
ID: 103, Grade: C
ID: 102, Grade: B
ID: 101, Grade: A
Conclusion
map
is a powerful associative container in C++ STL that stores key-value pairs.- It automatically sorts the keys in ascending order by default, but you can customize the sorting using comparators.
- Basic operations include insertion, access, deletion, and iteration.
- Advanced topics include custom comparators, multi-maps, and using complex types as keys.
.
.