-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmerge_sort.h
More file actions
executable file
·87 lines (71 loc) · 3.44 KB
/
merge_sort.h
File metadata and controls
executable file
·87 lines (71 loc) · 3.44 KB
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
#pragma once
#include "utility.h" // for DefaultComparator
#include <algorithm> // for std::copy
#include <iterator> // for std::iterator_traits
#include <vector> // for std::vector
namespace cs
{
template <typename T, typename TComparator = DefaultComparator<T> >
static std::vector<T> merge(const std::vector<T>& a, const std::vector<T>& b)
{
std::vector<T> result;
result.reserve(a.size() + b.size());
size_t a_i = 0;
size_t b_i = 0;
while (a_i < a.size() && b_i < b.size())
{
if (TComparator::LessThan(a[a_i], b[b_i]))
result.push_back(a[a_i++]);
else
result.push_back(b[b_i++]);
}
while (a_i < a.size())
result.push_back(a[a_i++]);
while (b_i < b.size())
result.push_back(b[b_i++]);
return result;
}
template <typename TIterator, typename TComparator = DefaultComparator<typename TIterator::value_type> >
static std::vector<typename TIterator::value_type> merge_sort_internal(TIterator begin, TIterator end)
{
auto size = std::distance(begin, end);
if (size == 0)
return std::vector<typename TIterator::value_type>();
else if (size == 1)
return std::vector<typename TIterator::value_type>(1, *begin);
auto middle = begin + size / 2;
auto left_part = merge_sort_internal<TIterator, TComparator>(begin, middle);
auto right_part = merge_sort_internal<TIterator, TComparator>(middle, end);
return merge<typename TIterator::value_type, TComparator>(left_part, right_part);
}
/**
* @brief Sort specified range of values using merge sort algorithm.
* Idea: divide an array into two halves (need to allocate space for them),
* sort each half separately using merge sort (recursion) and merge them again into the full array.
* Complexity: O(NlgN).
* Space complexity: O(N).
*
* @tparam TIterator Iterator type (must be a random access iterator).
* @tparam TComparator Comparator type (must have a static member function bool LessThan(const T& a, const T& b)
* where T is the value type of container being sorted). For example @see DefaultComparator, @see ReverseComparator.
*
* @param begin - Iterator specifying the beginning of a range to be sorted.
* @param end - Iterator specifying the end of a range to be sorted.
*/
template <typename TIterator, typename TComparator = DefaultComparator<typename TIterator::value_type> >
void merge_sort(TIterator begin, TIterator end)
{
// Check that TIterator is a random-access iterator
static_assert(
std::is_same<typename std::iterator_traits<TIterator>::iterator_category,
std::random_access_iterator_tag>::value,
"TIterator must be a random-access iterator.");
// Check for the existence of a member function "LessThan" in TComparator type
static_assert(
std::is_same<decltype(&TComparator::LessThan),
bool (*)(const typename TIterator::value_type&, const typename TIterator::value_type&)>::value,
"LessThan function is missing in TComparator");
auto result = merge_sort_internal<TIterator, TComparator>(begin, end);
std::copy(result.begin(), result.end(), begin);
}
}