Namespaces
Variants
Views
Actions

std::ranges::inplace_merge

From cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms: std::ranges::copy, std::ranges::sort, ...
Execution policies (C++17)
Non-modifying sequence operations
(C++11)(C++11)(C++11)
(C++17)
Modifying sequence operations
Operations on uninitialized storage
Partitioning operations
Sorting operations
(C++11)
Binary search operations
Set operations (on sorted ranges)
Heap operations
(C++11)
Minimum/maximum operations
(C++11)
(C++17)

Permutations
Numeric operations
C library
 
Constrained algorithms
Non-modifying sequence operations
Modifying sequence operations
Operations on uninitialized storage
Partitioning operations
Sorting operations
Binary search operations
Set operations (on sorted ranges)
ranges::inplace_merge
Heap operations
Minimum/maximum operations
Permutations
 
Defined in header <algorithm>
Call signature
template< std::bidirectional_iterator I, std::sentinel_for<I> S,

          class Comp = ranges::less, class Proj = std::identity >
requires std::sortable<I, Comp, Proj>

I ranges::inplace_merge( I first, I middle, S last, Comp comp = {}, Proj proj = {} );
(1) (since C++20)
template< ranges::bidirectional_range R, class Comp = ranges::less,

          class Proj = std::identity >
requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
ranges::borrowed_iterator_t<R>

ranges::inplace_merge( R&& r, iterator_t<R> middle, Comp comp = {}, Proj proj = {} );
(2) (since C++20)

Merges two consecutive sorted ranges [first, middle) and [middle, last) into one sorted range [first, last).

A sequence is said to be sorted with respect to the comparator comp and projection proj if for any iterator it pointing to the sequence and any non-negative integer n such that it + n is a valid iterator pointing to an element of the sequence, std::invoke(comp, std::invoke(proj, *(it + n)), std::invoke(proj, *it))) evaluates to false.

This merge function is stable, which means that for equivalent elements in the original two ranges, the elements from the first range (preserving their original order) precede the elements from the second range (preserving their original order).

1) Elements are compared using the given binary comparison function comp and projection object proj, and the ranges must be sorted with respect to the same.
2) Same as (1), but uses r as the range, as if using ranges::begin(r) as first, and ranges::end(r) as last.

The function-like entities described on this page are niebloids, that is:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

first - the beginning of the first sorted range
middle - the end of the first range and the beginning of the second range
last - the end of the second sorted range
r - the range of elements to merge inplace
comp - comparison to apply to the projected elements
proj - projection to apply to the elements in the range.

[edit] Return value

An iterator equal to last.

[edit] Complexity

Exactly N−1 comparisons, if additional memory buffer is available, where N = ranges::distance(first, last). Otherwise, 𝓞(N•log(N)) comparisons. Additionally, twice as many projections as comparisons in both cases.

[edit] Notes

This function attempts to allocate a temporary buffer. If the allocation fails, the less efficient algorithm is chosen.

[edit] Example

#include <algorithm>
#include <complex>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
 
void print(auto const& v, auto const& rem, int middle = -1)
{
    for (int i{}; auto n : v)
        std::cout << (i++ == middle ? "│ " : "") << n << ' ';
    std::cout << rem << '\n';
}
 
template <std::random_access_iterator I, std::sentinel_for<I> S>
requires std::sortable<I>
void merge_sort(I first, S last)
{
    if (last - first > 1) {
        I middle {first + (last - first) / 2};
        merge_sort(first, middle);
        merge_sort(middle, last);
        std::ranges::inplace_merge(first, middle, last);
    }
}
 
int main()
{
    // custom merge-sort demo
    std::vector v {8, 2, 0, 4, 9, 8, 1, 7, 3};
    print(v, ": before sort");
    merge_sort(v.begin(), v.end());
    print(v, ": after sort\n");
 
    // merging with comparison function object and projection
    using CI = std::complex<int>;
    std::vector<CI> r { {0,1}, {0,2}, {0,3}, {1,1}, {1,2} };
    const auto middle { std::ranges::next(r.begin(), 3) };
    auto comp { std::ranges::less{} };
    auto proj { [](CI z) { return z.imag(); } };
 
    print(r, ": before merge", middle - r.begin());
    std::ranges::inplace_merge(r, middle, comp, proj);
    print(r, ": after merge");
}

Output:

8 2 0 4 9 8 1 7 3 : before sort
0 1 2 3 4 7 8 8 9 : after sort
 
(0,1) (0,2) (0,3) │ (1,1) (1,2) : before merge
(0,1) (1,1) (0,2) (1,2) (0,3) : after merge

[edit] See also

merges two sorted ranges
(niebloid) [edit]
computes the union of two sets
(niebloid) [edit]
checks whether a range is sorted into ascending order
(niebloid) [edit]
sorts a range into ascending order
(niebloid) [edit]
merges two ordered ranges in-place
(function template) [edit]