std::multiset


STL container: std::multiset

std::multiset is a container in the C++ Standard Template Library (STL) that stores elements in a sorted order, allowing multiple elements with the same value. Like std::set, it is typically implemented as a balanced binary search tree (usually a red-black tree), providing logarithmic time complexity for insertion, deletion, and search operations.

Key Characteristics

Example 1: Basic Usage

#include <iostream>
#include <set>
#include <string>

int main() {
    std::multiset<int> numbers = {5, 2, 8, 2, 1, 9, 3, 7, 3};

    // Inserting elements
    numbers.insert(4);
    numbers.insert(2);  // Duplicate allowed

    // Printing the multiset
    std::cout << "Numbers in the multiset:" << std::endl;
    for (const auto& num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Counting occurrences
    std::cout << "Count of 2: " << numbers.count(2) << std::endl;

    // Finding elements
    auto range = numbers.equal_range(3);
    std::cout << "Elements equal to 3: ";
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // Removing an element
    numbers.erase(numbers.find(3));  // Removes only one instance of 3

    // Size of the multiset
    std::cout << "Number of elements: " << numbers.size() << std::endl;

    return 0;
}

Explanation:

Example 2: Custom Comparator for Descending Order

#include <iostream>
#include <set>
#include <string>

struct Person {
    std::string name;
    int age;

    // This is used for printing
    friend std::ostream& operator<<(std::ostream& os, const Person& p) {
        return os << p.name << " (" << p.age << ")";
    }
};

// Custom comparator for descending order of age
struct PersonComparator {
    bool operator()(const Person& a, const Person& b) const {
        if (a.age != b.age) {
            return a.age > b.age;  // Descending order of age
        }
        return a.name < b.name;  // Ascending order of name if ages are equal
    }
};

int main() {
    std::multiset<Person, PersonComparator> people;

    people.insert({"Alice", 30});
    people.insert({"Bob", 25});
    people.insert({"Charlie", 35});
    people.insert({"David", 30});
    people.insert({"Eve", 25});

    for (const auto& person : people) {
        std::cout << person << std::endl;
    }

    return 0;
}

Explanation:

Example 3: Frequency Count and Element Removal

#include <iostream>
#include <set>
#include <string>
#include <map>

int main() {
    std::multiset<std::string> words = {
        "apple", "banana", "cherry", "date", "apple", "fig",
        "grape", "apple", "banana", "elderberry"
    };

    // Count frequency of each word
    std::map<std::string, int> frequency;
    for (const auto& word : words) {
        frequency[word]++;
    }

    // Print frequency
    std::cout << "Word frequencies:" << std::endl;
    for (const auto& pair : frequency) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // Remove all instances of a specific word
    std::string word_to_remove = "apple";
    auto removed = words.erase(word_to_remove);
    std::cout << "\nRemoved " << removed << " instance(s) of '" << word_to_remove << "'" << std::endl;

    // Print remaining words
    std::cout << "\nRemaining words:" << std::endl;
    for (const auto& word : words) {
        std::cout << word << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation:

4. Range Operations and Lower/Upper Bounds

#include <iostream>
#include <set>
#include <algorithm>

void printRange(const std::multiset<int>& ms, int lower, int upper) {
    auto start = ms.lower_bound(lower);
    auto end = ms.upper_bound(upper);

    std::cout << "Elements in range [" << lower << ", " << upper << "]: ";
    std::for_each(start, end, [](int n) { std::cout << n << " "; });
    std::cout << std::endl;
}

int main() {
    std::multiset<int> numbers = {1, 2, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 10};

    std::cout << "All numbers: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Demonstrate lower_bound and upper_bound
    printRange(numbers, 3, 7);

    // Count elements in a range
    int rangeStart = 4, rangeEnd = 8;
    auto startIt = numbers.lower_bound(rangeStart);
    auto endIt = numbers.upper_bound(rangeEnd);
    int count = std::distance(startIt, endIt);
    std::cout << "Number of elements between " << rangeStart 
              << " and " << rangeEnd << ": " << count << std::endl;

    // Remove a range of elements
    numbers.erase(numbers.lower_bound(5), numbers.upper_bound(8));

    std::cout << "After removing range [5, 8]: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

Explanation:

Additional Considerations

  1. Performance: While multiset provides good performance for most operations, consider using std::vector or std::deque for small datasets or when frequent insertions/deletions are not required.

  2. Memory Usage: multiset typically uses more memory than a simple array due to its tree structure.

  3. Iteration Order: Elements are always traversed in the sorted order defined by the comparison function.

  4. No Direct Element Modification: Elements in a multiset cannot be modified directly through iterators to maintain the correct ordering.

Summary

std::multiset is a powerful container in C++ for storing sorted elements while allowing duplicates. Key points to remember:

std::multiset is particularly useful in situations where you need to maintain a sorted collection of elements, including duplicates. It's commonly used in scenarios such as: - Implementing algorithms that require sorted data with repetitions - Frequency analysis of elements - Maintaining ordered lists where duplicates are meaningful - Scenarios where both sorting and the ability to store multiple identical elements are crucial

Understanding when to use std::multiset over other containers like std::set or std::vector is key to writing efficient and clear C++ code in various application domains.

Related

Previous Page | Course Schedule | Course Content