Exploring unordered_map in C++


The unordered_map in C++ is a powerful container that stores elements in the form of key-value pairs. It provides efficient average time complexity for insertion, deletion, and search operations, making it ideal for scenarios where fast lookups are required.

Introduction to unordered_map

An unordered_map is implemented using a hash table, which allows for fast access to elements based on their keys. Keys in an unordered_map are unique, and the elements are not stored in any particular order, unlike map which maintains elements in a sorted order based on keys.

Key Operations

Let's dive into the fundamental operations you can perform with unordered_map: insertion, search, and deletion.

1. Insertion

Inserting elements into an unordered_map is straightforward. If the key already exists, its associated value is updated. If the key does not exist, a new key-value pair is added.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap;

    // Inserting key-value pairs
    umap["apple"] = 2;
    umap["banana"] = 3;
    umap.insert({"cherry", 5});

    // Display contents after insertion
    for (const auto& pair : umap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

In the example above:

  • umap["apple"] = 2; inserts or updates the key "apple" with the value 2.

  • umap.insert({"cherry", 5}); inserts a new key-value pair "cherry" with the value 5.

Searching for an element in an unordered_map involves using the find function, which returns an iterator to the element if found, or umap.end() if not found.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap;
    umap["apple"] = 2;
    umap["banana"] = 3;

    // Searching for a key
    auto it = umap.find("banana");
    if (it != umap.end()) {
        std::cout << "Found " << it->first << " with value " << it->second << std::endl;
    } else {
        std::cout << "banana not found" << std::endl;
    }

    return 0;
}

Here:

  • umap.find("banana"); searches for the key "banana" in umap.

  • If found (it != umap.end()), it prints the key and value; otherwise, it indicates that the key was not found.

3. Deletion

To remove an element from an unordered_map, you can use the erase function, either by key or by iterator.

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap;
    umap["apple"] = 2;
    umap["banana"] = 3;

    // Deleting a key
    umap.erase("apple");

    // Display contents after deletion
    for (const auto& pair : umap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}
  • umap.erase("apple"); removes the key "apple" and its associated value from umap.

Using auto with unordered_map

The auto keyword simplifies the declaration of iterators, especially in complex types like unordered_map.

  • auto& pair : umap allows iterating over each key-value pair in umap without explicitly declaring the type of the iterator.

  • auto it = umap.find("banana"); declares it as an iterator that points to the key "banana" in umap.

Useful Functions in unordered_map

Here are some useful functions provided by unordered_map:

  • insert: Inserts a key-value pair into the map.

  • find: Searches for a key and returns an iterator to it.

  • erase: Removes an element by key or by iterator.

  • size: Returns the number of elements in the map.

  • empty: Checks if the map is empty.

  • clear: Removes all elements from the map.

Functions of unordered_map

1. insert

The insert function inserts a key-value pair into the unordered_map. If the key already exists, the insertion is ignored.

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap;

    // Insert using insert function
    umap.insert({"apple", 2});
    umap.insert({"banana", 3});
    umap.insert({"cherry", 5});

    // Display contents
    for (const auto& pair : umap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

2. find

The find function searches for a key in the map and returns an iterator pointing to the key-value pair if found, or umap.end() if not found.

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap = {{"apple", 2}, {"banana", 3}, {"cherry", 5}};

    // Searching for a key
    auto it = umap.find("banana");
    if (it != umap.end()) {
        std::cout << "Found " << it->first << " with value " << it->second << std::endl;
    } else {
        std::cout << "banana not found" << std::endl;
    }

    return 0;
}

3. erase

The erase function removes an element from the map by key or by iterator.

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap = {{"apple", 2}, {"banana", 3}, {"cherry", 5}};

    // Erasing a key
    umap.erase("apple");

    // Display contents after deletion
    for (const auto& pair : umap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

4. size

The size function returns the number of key-value pairs in the map.

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap = {{"apple", 2}, {"banana", 3}, {"cherry", 5}};

    // Get the size of the map
    std::cout << "Size of umap: " << umap.size() << std::endl;

    return 0;
}

5. empty

The empty function checks if the map is empty (i.e., contains no elements) and returns true if empty, false otherwise.

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap;

    // Check if map is empty
    if (umap.empty()) {
        std::cout << "Map is empty" << std::endl;
    } else {
        std::cout << "Map is not empty" << std::endl;
    }

    return 0;
}

6. clear

The clear function removes all elements from the map.

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap = {{"apple", 2}, {"banana", 3}, {"cherry", 5}};

    // Clear all elements
    umap.clear();

    // Check if map is empty after clearing
    if (umap.empty()) {
        std::cout << "Map is empty" << std::endl;
    } else {
        std::cout << "Map is not empty" << std::endl;
    }

    return 0;
}

7. operator[]

The operator[] allows accessing or inserting elements using a key. If the key exists, it returns a reference to its associated value; if not, it inserts the key with a default value (0 for int).

Example:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap;

    // Inserting or updating using operator[]
    umap["apple"] = 2;
    umap["banana"] = 3;

    // Accessing using operator[]
    std::cout << "Value of apple: " << umap["apple"] << std::endl;

    return 0;
}

Iterating Through unordered_map

To iterate through all elements in an unordered_map, you can use a range-based for loop or iterator-based loop.

Example (Range-based for loop):

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap = {{"apple", 2}, {"banana", 3}, {"cherry", 5}};

    // Using range-based for loop to iterate
    for (const auto& pair : umap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    return 0;
}

Example (Iterator-based loop):

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> umap = {{"apple", 2}, {"banana", 3}, {"cherry", 5}};

    // Using iterator to iterate
    for (auto it = umap.begin(); it != umap.end(); ++it) {
        std::cout << it->first << ": " << it->second << std::endl;
    }

    return 0;
}

Conclusion

Understanding the functions provided by unordered_map allows you to effectively manage key-value pairs in C++. These functions provide essential operations like insertion, search, deletion, size checking, and clearing, making unordered_map a versatile choice for handling associative arrays.

By mastering these concepts and examples, you'll be equipped to utilize unordered_map efficiently in your C++ projects, ensuring fast and efficient data retrieval and manipulation.


Did you find this article valuable?

Support Sarthak by becoming a sponsor. Any amount is appreciated!