# 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; } ```