This is the 13th Part of Tutorial series on unordered_map. In this tutorial, we’ll learn how to customize the hashing function used by an unordered_map in C++. This is particularly useful when dealing with complex keys or optimizing performance.

An unordered_map is an associative container provided by C++. It uses a hash function to map keys to their corresponding values. By default, it uses a standard hashing function i.e. std::hash() for common data types like int, string, etc. However, for custom data types or to enhance performance, you might want to use a custom hash function.

Characterstics of Custom Hash Function

A custom hash function must meet certain criteria:
1. Consistency: It should return the same hash value for the same input every time.
2. Efficiency: It should compute the hash value quickly.
3. Uniformity: It should distribute hash values uniformly across the hash table to minimize collisions.

We need to create Custom hash Function as aFunction Object. Here’s an example of a custom hash function for a simple string key:

#include <iostream>
#include <unordered_map>
#include <string>
#include <functional>

struct CustomStringHash 
{
    std::size_t operator()(const std::string& key) const 
    {
        std::size_t hashValue = 0;
        for (char c : key) {
            hashValue = 37 * hashValue + c;
        }
        return hashValue;
    }
};

This function accepts a string as an argument and creates a unique hash value for that string. It iterates through each character of the given string and multiplies each character’s ASCII value by 37. It then adds all those numbers to calculate the hash value. The number 37 is a prime number, often used in hashing to achieve a more uniform distribution of hash values.”

Implementing a Custom Hash Function in Unordered_Map

To use the custom hash function in an unordered_map, we need to pass it as a template parameter when declaring the unordered_map, like this,

// Define an unordered_map with a custom hash function
std::unordered_map<std::string, int, CustomStringHash> wordFrequency;

Now, this unordered_map object will use the custom hash function, i.e., CustomStringHash, while calculating the hash value of a key. Let’s see the complete example,

int main() 
{
    // Define an unordered_map with a custom hash function
    std::unordered_map<std::string, int, CustomStringHash> wordFrequency;

    // Adding elements to the map
    wordFrequency["Why"]   = 11;
    wordFrequency["Where"] = 22;
    wordFrequency["How"]   = 33;

    // Accessing the elements
    for (const auto& pair : wordFrequency)
    {
        std::cout << pair.first << " has value: " << pair.second << std::endl;
    }

    return 0;
}

Output:

How has value: 33
Where has value: 22
Why has value: 11

In the main() function, we declare an unordered_map named wordFrequency that uses our CustomStringHash as the hashing function. We add a few elements to the map and then iterate over it to print the key-value pairs.

Summary

Customizing the hash function in an unordered_map allows for greater control over how keys are hashed, which can be essential for performance optimization and handling complex key types. Today we learned how to create and implement a custom hash function, illustrating its use in an unordered_map with string keys.

Ritika Ohri

Hi, I am Ritika Ohri, founder of this blog. I craft comprehensive programming tutorials and also manage a YouTube channel. You can also connect with me on Linkedin.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.