Initialize Multi-Set with Custom Comparator in C++



In this article, we will learn how to initialize a std::multiset with a custom comparator in C++. A multiset is similar to a set, except that it allows duplicate elements. It stores elements in a sorted order based on a comparison function.

By default, elements are compared using the < (less-than) operator. However, with a custom comparator, we can define how elements should be compared. For example, if we define a custom comparator that sorts elements in descending order and insert the following elements into the multiset:

Input: 3 12 5 8 1 7 9 4 6

Output: {12, 9, 8, 7, 6, 5, 4, 3, 1}

We will explain how to implement and use a custom comparator in C++ to change the default sorting behavior, with an example to illustrate the process.

Initializing a Multiset with a Custom Comparator

To initialize a multiset with a custom comparator, we need to define a custom function or functor that specifies how elements should be compared. This comparator is then passed as a parameter to the multiset to control the sorting order.

Let's look at three common ways to define a custom comparator:

Using a Function Pointer

In this approach, we define a custom function that compares two elements and returns true if one should be ordered before the other. This function is then passed to the std::multiset constructor to control the sorting order.

Example

In this example, we create a function (customComparator) that sorts elements in descending order. The function is passed to the multiset constructor, which uses it to store and order the elements accordingly.

#include <iostream>
#include <set>
#include <functional>

using namespace std;

// Comparator function to compare elements in descending order
bool customComparator(int a, int b) {
   return a > b;  // Elements will be sorted in descending order
}

int main() {
   // Initialize multiset with a custom comparator
   multiset<int, function<bool(int, int)>> myMultiset(customComparator);
   
   // Insert elements
   myMultiset.insert(10);
   myMultiset.insert(30);
   myMultiset.insert(20);
   myMultiset.insert(40);
   
   // Display elements in sorted order
   cout << "After inserting elements: " << endl;
   for (auto element : myMultiset) {
      cout << element << " ";
   }
   cout << endl;
   
   return 0;
}

Below is the output that shows the elements displayed in descending order:

After inserting elements: 
40 30 20 10  

Time Complexity: Complexity:O(n log n), with each of the n insertions taking O(log n) due to the balanced tree structure.

Space Complexity: O(n), as the multiset stores n elements.

Using a Function Object (Functor)

In this approach, we define a class (functor) that overloads the () operator to implement the custom comparison logic. This functor is then passed to the std::multiset constructor to control the ordering of the elements

Example

In this example, we use a functor (CustomComparator) to compare elements in descending order. The functor is passed to the std::multiset constructor to control the ordering of elements.

#include <iostream>
#include <set>

using namespace std;

// Functor class to compare elements in descending order
class CustomComparator {
public:
   bool operator()(int a, int b) const {
      return a > b;  // Elements will be sorted in descending order
   }
};

int main() {
   // Initialize multiset with a custom comparator (using functor)
   multiset<int, CustomComparator> myMultiset;
   
   // Insert elements
   myMultiset.insert(10);
   myMultiset.insert(30);
   myMultiset.insert(20);
   myMultiset.insert(40);
   
   // Display elements in sorted order
   cout << "After inserting elements: " << endl;
   for (auto element : myMultiset) {
      cout << element << " ";
   }
   return 0;
}

The output below shows the elements ordered in descending order:

After inserting elements: 
40 30 20 10 

Time Complexity: O(n log n) due to n insertions, each taking O(log n), and O(n) for iteration.

Space Complexity: O(n) because the multiset stores n elements.

Using a Lambda Expression

In this approach, we use a lambda expression to define a custom comparator inline. A lambda expression is an anonymous function that allows us to specify the comparison logic directly when initializing the multiset.

Example

In this example, we define a lambda function(comparator) that compares two integers in descending order. We then use this lambda as a custom comparator to initialize the multiset. The elements are then inserted and displayed in sorted order.

#include <iostream>
#include <set>
#include <functional>

int main() {
   // Using lambda as a comparator
   auto comp = [](const int& a, const int& b) { return a > b; };   
   std::multiset<int, decltype(comp)> myMultiset(comp);
   
   // Add elements
   myMultiset.insert({10, 30, 20, 40});
   
   // Print the elements
   std::cout << "After inserting elements: "<< std::endl ;
   for (const auto& elem : myMultiset) {
      std::cout << elem << " ";
   }
   return 0;
}

Below is the output showing the elements displayed in descending order:

After inserting elements: 
40 30 20 10

Time Complexity: O(n log n) due to n insertions, each taking O(log n), and O(n) for iteration.

Space Complexity: O(n) because the multiset stores n elements.

Conclusion

In this article, we explained how to initialize a std::multiset with a custom comparator using three methods: function pointer, functor, and lambda expression. Each method allows us to define how the elements should be sorted based on our needs.

Updated on: 2025-03-27T14:47:12+05:30

76 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements