File: algorithm.hpp

package info (click to toggle)
python-pyclustering 0.10.1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 11,128 kB
  • sloc: cpp: 38,888; python: 24,311; sh: 384; makefile: 105
file content (119 lines) | stat: -rwxr-xr-x 3,651 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*!

@authors Andrei Novikov (pyclustering@yandex.ru)
@date 2014-2020
@copyright BSD-3-Clause

*/

#pragma once


#include <iterator>


namespace pyclustering {

namespace utils {

namespace algorithm {


/*!

@brief Returns the element at the left side from the right border with the same value as the 
        last element in the range `[p_begin, p_end)`.
@details The element at the right is considered as target to search. `[p_begin, p_end)` must 
         be sorted collection. `InputIt` must meet the requirements of `LegacyInputIterator` 
         and `LegacyRandomAccessIterator`. The complexity of the algorithm is `O(log(n))`. The 
         algorithm is based on the binary search algorithm.

@param[in] p_begin: iterator pointing to the first element.
@param[in] p_end: iterator pointing to the end of the range.
@param[in] p_comparator: comparison function object which returns `true` if the first argument
            is less than the second. The signature of the compare function should be equivalent
            to the following: `bool comparator(const Type & p_val1, const Type & p_val2)`.

@return The element at the left side from the right border with the same value as the 
         last element in the range `[p_begin, p_end)`.

*/
template <class InputIt, class Comparator>
InputIt find_left_element(const InputIt p_begin, const InputIt p_end, Comparator p_comparator) {
    if (p_begin == p_end) {
        return p_end;
    }

    InputIt left = p_begin, right = p_end - 1;
    InputIt middle = p_begin + (std::distance(left, right) / 2);
    auto target = *right;

    while (left < right) {
        if (p_comparator(*middle, target)) {
            left = middle + 1;
        }
        else {
            right = middle;
        }

        const auto offset = std::distance(left, right) / 2;
        middle = left + offset;
    }

    return left;
}


/*!

@brief Returns the element at the left side from the right border with the same value as the 
        last element in the range `[p_begin, p_end)`.
@details The element at the right is considered as target to search. `[p_begin, p_end)` must 
         be sorted collection. `InputIt` must meet the requirements of `LegacyInputIterator` 
         and `LegacyRandomAccessIterator`. The complexity of the algorithm is `O(log(n))`. The 
         algorithm is based on the binary search algorithm.

@param[in] p_begin: iterator pointing to the first element.
@param[in] p_end: iterator pointing to the end of the range.

@return The element at the left side from the right border with the same value as the 
         last element in the range `[p_begin, p_end)`.

@code
    #include <iterator>
    #include <vector>
    #include <iostream>

    #include <pyclustering/utils/algorithm.hpp>

    using namespace pyclustering::utils::algorithm;

    int main() {
        std::vector<int> seq = { 1, 2, 2, 3, 3, 3, 6, 6, 6 };

        for (auto iter = seq.begin() + 1; iter != seq.end(); iter++) {
            auto left = find_left_element(seq.begin(), iter);
            std::cout << "Index of the left element: " << std::distance(seq.begin(), left)
                << " for " << *iter << std::endl;
        }

        return 0;
    }
@endcode

*/
template <class InputIt>
InputIt find_left_element(const InputIt p_begin, const InputIt p_end) {
    using iter_type = typename std::iterator_traits<InputIt>::value_type;

    return find_left_element(p_begin, p_end, [](iter_type & p_val1, iter_type & p_val2) {
        return p_val1 < p_val2;
    });
}


}

}

}