-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsorting_algo.hpp
124 lines (95 loc) · 3.15 KB
/
sorting_algo.hpp
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
120
121
122
123
124
#pragma once
#include <algorithm>
#include <span>
#include "sorting_task.hpp"
namespace sortviz
{
tnt::sorting_task bubble_sort(std::span<unsigned> numbers)
{
auto const n_1 = numbers.size() - 1;
for (std::size_t i{}; i < n_1; ++i)
{
bool swapped = false;
for (std::size_t j{}; j < n_1 - i; ++j)
{
co_yield {i, j};
if (numbers[j] > numbers[j + 1])
{
std::swap(numbers[j], numbers[j + 1]);
swapped = true;
}
}
if (!swapped)
break;
}
}
tnt::sorting_task selection_sort(std::span<unsigned> numbers)
{
auto const n = numbers.size();
auto const n_1 = n - 1;
for (std::size_t i{}; i < n_1; ++i)
{
std::size_t min_idx = i;
for (std::size_t j{i + 1}; j < n; ++j)
{
co_yield {i, j};
if (numbers[j] < numbers[min_idx])
min_idx = j;
}
std::swap(numbers[i], numbers[min_idx]);
}
}
tnt::sorting_task quick_sort(std::span<unsigned> numbers)
{
if (numbers.size() > 1)
{
auto const pivot = numbers.back();
auto const pivot_it = std::partition(numbers.begin(), numbers.end() - 1,
[pivot](auto const &n)
{ return n < pivot; });
co_yield {std::size_t(pivot_it - numbers.begin()), numbers.size() - 1};
std::swap(*pivot_it, numbers.back());
auto const mid = pivot_it - numbers.begin();
auto const left = numbers.subspan(0, mid);
auto const right = numbers.subspan(mid + 1);
for (auto [i, j] : quick_sort(left))
co_yield {i, j};
for (auto [i, j] : quick_sort(right))
co_yield {i + mid + 1, j + mid + 1};
}
}
tnt::sorting_task heapify(std::span<unsigned> numbers, std::size_t n, std::size_t i)
{
auto largest = i;
auto const l = 2 * i + 1;
auto const r = 2 * i + 2;
if (l < n && numbers[l] > numbers[largest])
largest = l;
if (r < n && numbers[r] > numbers[largest])
largest = r;
if (largest != i)
{
co_yield {i, largest};
std::swap(numbers[i], numbers[largest]);
for (auto [i, j] : heapify(numbers, n, largest))
co_yield {i, j};
}
}
tnt::sorting_task heap_sort(std::span<unsigned> numbers)
{
auto const n = numbers.size();
auto const pn = std::ptrdiff_t(n);
for (std::ptrdiff_t i{pn / 2 - 1}; i >= 0; --i)
{
for (auto [i, j] : heapify(numbers, n, i))
co_yield {i, j};
}
for (std::ptrdiff_t i{pn - 1}; i >= 0; --i)
{
co_yield {0, std::size_t(i)};
std::swap(numbers[0], numbers[i]);
for (auto [i, j] : heapify(numbers, i, 0))
co_yield {i, j};
}
}
}