# Collections: C++
## Vector
A vector in C++ is a dynamic array that allows efficient insertion and removal of elements at the end. It provides random access to elements.
```cpp!
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
// Declaration and Initialization
std::vector<int> vec = {1, 2, 3};
// Adding Elements to End
vec.push_back(4);
// Accessing Elements
std::cout << "First Element: " << vec[0] << std::endl;
// Updating Elements
vec[1] = 22;
// Removing Elements From End
vec.pop_back();
// Checking if an Element Exists
bool containsElement = std::find(vec.begin(), vec.end(), 2) != vec.end();
std::cout << "Contains Element 2: " << containsElement << std::endl;
// Getting the Size
std::cout << "Size of Vector: " << vec.size() << std::endl;
// Iterating Through Elements
for (int element : vec) {
std::cout << element << " ";
}
std::cout << std::endl;
// Checking if the Vector is Empty
bool isEmpty = vec.empty();
std::cout << "Is Vector Empty: " << isEmpty << std::endl;
// Clearing All Elements
vec.clear();
std::cout << "Vector after clearing: ";
for (int element : vec) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
```
## Stack
A stack in C++ is a Last In First Out (LIFO) data structure. Elements are added (pushed) and removed (popped) from the top.
```cpp!
#include <iostream>
#include <stack>
int main() {
// Declaration
std::stack<int> stack;
// Pushing Elements
stack.push(1);
stack.push(2);
stack.push(3);
// Accessing the Top Element
std::cout << "Top Element: " << stack.top() << std::endl;
// Popping Elements
stack.pop();
// Checking if the Stack is Empty
bool isEmpty = stack.empty();
std::cout << "Is Stack Empty: " << isEmpty << std::endl;
return 0;
}
```
## List
A list in C++ is a doubly-linked list that allows efficient insertion and removal of elements at both ends. It does not provide random access.
```cpp!
#include <algorithm>
#include <iostream>
#include <list>
int main() {
// Declaration and Initialization
std::list<int> linkedList = {1, 2, 3};
// Adding Elements
linkedList.push_back(4);
linkedList.push_front(0);
// Accessing Elements
std::cout << "First Element: " << linkedList.front() << std::endl;
// Updating Elements
auto it = std::find(linkedList.begin(), linkedList.end(), 2);
if (it != linkedList.end()) {
*it = 22;
}
// Removing Elements
linkedList.pop_back();
linkedList.pop_front();
// Checking if an Element Exists
bool containsElement = std::find(linkedList.begin(), linkedList.end(), 2) != linkedList.end();
std::cout << "Contains Element 2: " << containsElement << std::endl;
// Getting the Size
std::cout << "Size of List: " << linkedList.size() << std::endl;
// Iterating Through Elements
for (int element : linkedList) {
std::cout << element << " ";
}
std::cout << std::endl;
// Checking if the List is Empty
bool isEmpty = linkedList.empty();
std::cout << "Is List Empty: " << isEmpty << std::endl;
// Clearing All Elements
linkedList.clear();
std::cout << "List after clearing: ";
for (int element : linkedList) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
```
## Unordered_set
An unordered_set in C++ is an unordered collection of unique elements. It uses a hash table to provide constant-time average complexity for common operations.
```cpp!
#include <iostream>
#include <unordered_set>
int main() {
// Declaration and Initialization
std::unordered_set<int> hashSet = {2, 4, 6, 8, 10};
// Adding Elements
hashSet.insert(12);
hashSet.insert(14);
// Accessing Elements
std::cout << "HashSet: ";
for (int element : hashSet) {
std::cout << element << " ";
}
std::cout << std::endl;
// Removing Elements
hashSet.erase(6);
// Checking if an Element Exists
bool containsElement = hashSet.find(8) != hashSet.end();
std::cout << "Contains Element 8: " << containsElement << std::endl;
// Iterating Through Elements
std::cout << "HashSet after removal: ";
for (int element : hashSet) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
```
## Set
A set in C++ is an ordered collection of unique elements. It automatically sorts elements in ascending order.
```cpp!
#include <iostream>
#include <set>
int main() {
// Declaration and Initialization
std::set<int> treeSet = {3, 1, 4, 1, 5, 9, 2, 6, 5};
// Accessing Elements (Automatically Sorted)
std::cout << "TreeSet: ";
for (int element : treeSet) {
std::cout << element << " ";
}
std::cout << std::endl;
// Removing Elements
treeSet.erase(4);
// Checking if an Element Exists
bool containsElement = treeSet.find(6) != treeSet.end();
std::cout << "Contains Element 6: " << containsElement << std::endl;
// Iterating Through Elements
std::cout << "TreeSet after removal: ";
for (int element : treeSet) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
```
## Unordered_map
An unordered_map in C++ is an unordered collection of key-value pairs. It uses a hash table to provide constant-time average complexity for common operations.
```cpp!
#include <iostream>
#include <unordered_map>
int main() {
// Declaration and Initialization
std::unordered_map<std::string, int> hashMap = {{"One", 1}, {"Two", 2}, {"Three", 3}};
// Adding Elements
hashMap["Four"] = 4;
// Accessing Elements
std::cout << "HashMap: ";
for (const auto& pair : hashMap) {
std::cout << pair.first << ":" << pair.second << " ";
}
std::cout << std::endl;
// Updating Elements
hashMap["Two"] = 22;
// Removing Elements
hashMap.erase("One");
// Checking if a Key Exists
bool containsKey = hashMap.find("Three") != hashMap.end();
std::cout << "Contains Key 'Three': " << containsKey << std::endl;
// Iterating Through Elements
std::cout << "HashMap after removal: ";
for (const auto& pair : hashMap) {
std::cout << pair.first << ":" << pair.second << " ";
}
std::cout << std::endl;
return 0;
}
```
## Map
A map in C++ is an ordered collection of key-value pairs. It automatically sorts elements based on the keys in ascending order.
```cpp!
#include <iostream>
#include <map>
int main() {
// Declaration and Initialization
std::map<std::string, int> linkedHashMap = {{"One", 1}, {"Two", 2}, {"Three", 3}};
// Adding Elements
linkedHashMap["Four"] = 4;
// Accessing Elements
std::cout << "LinkedHashMap: ";
for (const auto& pair : linkedHashMap) {
std::cout << pair.first << ":" << pair.second << " ";
}
std::cout << std::endl;
// Updating Elements
linkedHashMap["Two"] = 22;
// Removing Elements
linkedHashMap.erase("One");
// Checking if a Key Exists
bool containsKey = linkedHashMap.find("Three") != linkedHashMap.end();
std::cout << "Contains Key 'Three': " << containsKey << std::endl;
// Iterating Through Elements
std::cout << "LinkedHashMap after removal: ";
for (const auto& pair : linkedHashMap) {
std::cout << pair.first << ":" << pair.second << " ";
}
std::cout << std::endl;
return 0;
}
```
## Priority_queue
A priority_queue in C++ is a container that provides constant-time complexity for accessing the highest or lowest priority element.
```cpp!
#include <iostream>
#include <queue>
int main() {
// Declaration
std::priority_queue<int> priorityQueue;
// Adding Elements
priorityQueue.push(3);
priorityQueue.push(1);
priorityQueue.push(4);
priorityQueue.push(1);
priorityQueue.push(5);
// Printing the PriorityQueue
std::cout << "PriorityQueue: ";
while (!priorityQueue.empty()) {
std::cout << priorityQueue.top() << " ";
priorityQueue.pop();
}
std::cout << std::endl;
return 0;
}
```
## Deque
A deque in C++ is a double-ended queue that allows efficient insertion and removal of elements at both ends. It provides random access to elements.
```cpp!
#include <algorithm>
#include <deque>
#include <iostream>
int main() {
// Declaration and Initialization
std::deque<int> deque = {1, 2, 3};
// Adding Elements
deque.push_back(4);
deque.push_front(0);
// Accessing Elements
std::cout << "First Element: " << deque.front() << std::endl;
// Updating Elements
deque[1] = 22;
// Removing Elements
deque.pop_back();
deque.pop_front();
// Checking if an Element Exists
bool containsElement = std::find(deque.begin(), deque.end(), 2) != deque.end();
std::cout << "Contains Element 2: " << containsElement << std::endl;
// Getting the Size
std::cout << "Size of Deque: " << deque.size() << std::endl;
// Iterating Through Elements
std::cout << "Deque: ";
for (int element : deque) {
std::cout << element << " ";
}
std::cout << std::endl;
// Checking if the Deque is Empty
bool isEmpty = deque.empty();
std::cout << "Is Deque Empty: " << isEmpty << std::endl;
// Clearing All Elements
deque.clear();
std::cout << "Deque after clearing: ";
for (int element : deque) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
```
## Comparables
- In C++, the term "comparable" usually refers to types that can be compared using standard comparison operators (e.g., `<`, `<=`, `==`, `!=`, `>`, `>=`).
- For user-defined types, you can make them comparable by overloading these operators.
Here's an example of a comparable class in C++:
```cpp!
#include <iostream>
class Person {
public:
std::string name;
int age;
Person(std::string n, int a) : name(n), age(a) {}
// Overloading the < operator to make instances of Person comparable
bool operator<(const Person& other) const {
return age < other.age;
}
};
int main() {
Person person1("Alice", 28);
Person person2("Bob", 22);
if (person1 < person2) {
std::cout << person1.name << " is younger than " << person2.name << std::endl;
} else {
std::cout << person1.name << " is not younger than " << person2.name << std::endl;
}
return 0;
}
```
## Comparators
- In C++, comparators are typically implemented using function objects (functors) or lambda functions.
Here's an example of using a comparator to sort a collection of `Person` objects:
```cpp!
#include <algorithm>
#include <iostream>
#include <vector>
class Person {
public:
std::string name;
int age;
Person(std::string n, int a) : name(n), age(a) {}
};
// Functor (function object) to compare Person objects based on age
struct AgeComparator {
bool operator()(const Person& person1, const Person& person2) const {
return person1.age < person2.age;
}
};
int main() {
std::vector<Person> people = {{"Alice", 28}, {"Bob", 22}, {"Charlie", 25}};
// Sort the vector using the AgeComparator functor
std::sort(people.begin(), people.end(), AgeComparator());
// Iterate the vector of people and check if it is now sorted based on age
for (const Person& person : people) {
std::cout << person.name << " - " << person.age << '\t';
}
std::cout << std::endl;
// Sort the vector using comparator lambda
std::sort(people.begin(), people.end(), [](const Person& A, const Person& B) {
return A.age > B.age;
});
for (const Person& person : people) {
std::cout << person.name << " - " << person.age << '\t';
}
std::cout << std::endl;
return 0;
}
```