Unordered Multiset in C++ STL

Last Updated : 26 Jun, 2026

std::unordered_multiset is an unordered associative container in C++ STL that stores elements using a hash table and allows multiple occurrences of the same value. It provides efficient average-case insertion, deletion, and search operations while not maintaining any specific ordering of elements.

  • Supports duplicate elements and performs insertion, deletion, and search operations in average-case O(1) time.
  • Stores elements in an unordered manner using hashing rather than maintaining them in sorted order.
C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    
    // Create an empty unordered multiset
    unordered_multiset<int> ums1;
    
    // Create and initialize elements
    // using initialzer list
    unordered_multiset<int> ums2 =
                          {5, 3, 4, 1, 1};
    
    for(auto x : ums2)
        cout << x << " ";;
    return 0;
}

Output
1 1 4 3 5 

Explanation: In this example, we initialize an unordered multiset in three ways:

  • Statement unordered_multiset<int> ums1 creates an empty unordered multiset.
  • Statement unordered_multiset<int> ums2 = {1, 1, 4, 3, 5} initialize the unordered multiset using initializer list.

Syntax

unordered_multiset<T> ums;

Where:

  • T is the type of elements stored.
  • ums is the name of the unordered multiset.

To use std::unordered_multiset, include the following header:

#include <unordered_set>

Basic Operations

The basic operations of unordered multiset are shown below:

Inserting Elements

Elements can be inserted into an unordered multiset using the insert() method. The position of the element is determined by the hashing function so we cannot specify any position while inserting.

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    unordered_multiset<int> ums;
    
    // Insert elements using insert()
    ums.insert(5);
    ums.insert(1);
    ums.insert(3);
    ums.insert(1);
    ums.insert(2);
    ums.insert(4);
    
    for (auto x : ums) cout << x << ' ';
    return 0;
}

Output
4 2 5 1 1 3 

Explanation: Duplicate values are allowed and inserted into the container.

Accessing Elements

An unordered multiset does not allow direct access to elements by index as accessing elements is not the primary operation of this container. However, we have to increment or decrement iterator obtained from begin() or end() methods respectively to access the element by position. This can also be done with the help of next() or advance() function.

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    unordered_multiset<int> ums =
                    {5, 1, 3, 2, 4, 1};

    // Accessing element using iterator
    auto it = next(ums.begin(), 2);
    cout << *it;
    return 0;
}

Output
3

Explanation: iterator it accesses the third element by advancing begin() by 2 positions using next().

Updating Elements

Unordered multiset does allow changing the value of the accessed elements as it may disrupt the container functions.

C++
#include <iostream>
#include <unordered_set>
using namespace std;

int main() {

    unordered_multiset<int> ums = {1, 2, 3, 4};

    auto it = ums.find(2);

    // Error: elements of unordered_multiset
    // cannot be modified directly
    *it = 10;

    return 0;
}

Output

Compilation Error

Explanation: Elements stored in an unordered_multiset cannot be modified directly because altering a value may change its hash value and violate the container's internal organization. Therefore, iterators of unordered_multiset provide read-only access to elements.

Finding Elements

It is the primary operation for which this container is optimized for. The find() method provides fast search of any element by value. This function returns iterator to the element if found, otherwise returns iterator to the end().

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    unordered_multiset<int> ums =
                     {5, 1, 3, 4, 1};
    
    // Finding 3
    auto it = ums.find(3);
    
    if (it != ums.end()) cout << *it;
    else cout << "Element not Found!";
    return 0;
}

Output
3

Traversing Elements

We can traverse unordered multiset either using range-based for loop or using begin() and end() iterator.

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    unordered_multiset<int> ums =
                    {5, 1, 3, 4, 1};
    
    // Using range-based for loop
    for(auto x : ums)
        cout << x << " ";
    cout << "\n";
    
    return 0;
}

Output
5 1 1 3 4 

Deleting Elements

We can use erase() method to delete elements from unordered multiset. It deletes all occurrences of an elements if we provide the value of the element. If we provide iterator of the element, it deletes only that value from the unordered multiset.

C++
#include <bits/stdc++.h>
using namespace std;

int main() {
    unordered_multiset<int> ums =
                       {5, 1, 3, 2, 4, 1};

    // Delete all occurrences of element 1
    ums.erase(1);
    
    // Delete 2 using iterator
    ums.erase(ums.find(2));
    
   for (auto x: ums) cout << x << " ";
    return 0;
}
Try It Yourself
redirect icon

Output
4 3 5 

Explanation:

  • ums.erase(1) deletes all occurrences of the element 1 from the set.
  • ums.erase(ums.find(2)) deletes one occurrence of the element 2 by using an iterator returned from find(2).

Time Complexity

The below table lists the time complexity of the above operations on unordered multiset:

OperationTime Complexity
Inserting elementsO(1) average
Deleting elementsO(1) average
Finding elements by valueO(1) average
Accessing elements by positionO(n)
Traverse the multisetO(n)

Note: Due to hash collisions, the worst-case complexity of insertion, deletion, and searching can degrade to O(n).

Internal Working

std::unordered_multiset is implemented using a hash table.

  • Each element is mapped to a bucket using a hash function.
  • Elements with identical hash values are stored in the same bucket.
  • Buckets are typically implemented using linked lists or similar structures.
  • Hashing provides average-case constant time complexity for most operations.

Advantages of Unordered Multiset

std::unordered_multiset provides efficient storage and lookup for duplicate values.

  • Allows storing multiple occurrences of the same element.
  • Provides average-case constant-time insertion, deletion, and searching.
  • Offers better performance than multiset when ordering is not required.

Limitations of Unordered Multiset

Despite its advantages, unordered_multiset has some limitations.

  • Elements are not stored in sorted order.
  • Performance can degrade due to excessive hash collisions.
  • Does not support direct indexing or random access.

Common Member Functions

Following is the list of all member functions of std::unordered_multiset class in C++:

FunctionDescription
insert()Inserts elements into the container.
erase()Removes elements from the container.
find()Searches for an element.
count()Returns the number of occurrences of a value.
size()Returns the number of elements.
empty()Checks whether the container is empty.
clear()Removes all elements.
end(), end()Return iterators for traversal.
equal_range()Returns the range of elements matching a given value.
swap()Swaps the contents of two unordered multisets.
bucket_count()Returns the total number of buckets.
load_factor()Returns the current load factor.
rehash()Changes the number of buckets.

Related article:

Comment