LAL: Linear Arrangement Library 23.01.00
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
counting_sort.hpp
1/*********************************************************************
2 *
3 * Linear Arrangement Library - A library that implements a collection
4 * algorithms for linear arrangments of graphs.
5 *
6 * Copyright (C) 2019 - 2023
7 *
8 * This file is part of Linear Arrangement Library. The full code is available
9 * at:
10 * https://github.com/LAL-project/linear-arrangement-library.git
11 *
12 * Linear Arrangement Library is free software: you can redistribute it
13 * and/or modify it under the terms of the GNU Affero General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * Linear Arrangement Library is distributed in the hope that it will be
18 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with Linear Arrangement Library. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * Contact:
26 *
27 * LluĂ­s Alemany Puig (lalemany@cs.upc.edu)
28 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
29 * CQL (Complexity and Quantitative Linguistics Lab)
30 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
31 * Webpage: https://cqllab.upc.edu/people/lalemany/
32 *
33 * Ramon Ferrer i Cancho (rferrericancho@cs.upc.edu)
34 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office S124, Omega building
37 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
38 * Webpage: https://cqllab.upc.edu/people/rferrericancho/
39 *
40 ********************************************************************/
41
42#pragma once
43
44// C++ includes
45#include <functional>
46#include <tuple>
47
48// lal includes
49#include <lal/detail/data_array.hpp>
50#include <lal/detail/type_traits/is_pointer_iterator.hpp>
51#include <lal/detail/sorting/sorting_types.hpp>
52
53namespace lal {
54namespace detail {
55namespace sorting {
56
63namespace countingsort {
64
71template <typename T>
72struct memory {
77
79 memory() noexcept = default;
81 memory(const memory&) noexcept = default;
83 memory(memory&&) noexcept = default;
85 memory& operator= (const memory&) noexcept = default;
87 memory& operator= (memory&&) noexcept = default;
88
97 memory(const std::size_t largest_key_plus_1, const std::size_t max_size_container)
98 noexcept
99 : count(largest_key_plus_1, 0),
100 output(max_size_container)
101 { }
102
104 ~memory() noexcept = default;
105
107 void reset_count() noexcept { count.fill(0); }
108};
109
110} // -- namespace countingsort
111
141template <
142 typename value_t,
143 typename sort_type,
144 bool memory_has_frequencies,
145 typename value_iterator_t,
146 std::enable_if_t<
147 is_pointer_iterator_v<value_t, value_iterator_t> &&
148 (
149 std::is_same_v<sort_type, non_decreasing_t> ||
150 std::is_same_v<sort_type, non_increasing_t>
151 ),
152 bool
153 > = true
154>
156 const value_iterator_t begin, const value_iterator_t end,
157 const std::size_t largest_key_plus_1,
158 const std::function<std::size_t (const value_t&)>& key,
160)
161noexcept
162{
163 constexpr bool is_increasing =
164 std::is_same_v<sort_type, non_decreasing_t>;
165
166 if (begin == end) { return; }
167
168 if constexpr (not memory_has_frequencies) {
169 // calculate frequency of each element
170 for (auto it = begin; it != end; ) {
171 // get the key of the element into a variable so that
172 // the function is NOT called more than once per iteration
173 const std::size_t elem_key = key(*(it++));
174
175 ++mem.count[elem_key];
176 }
177 }
178
179 std::size_t total = 0;
180 for (std::size_t k = 0; k < largest_key_plus_1; ++k) {
181 std::tie(mem.count[k], total)
182 = std::make_pair(total, mem.count[k] + total);
183 }
184
185 std::size_t actual_container_size = 0;
186 for (auto it = begin; it != end; ) {
187 ++actual_container_size;
188
189 // get the key of the element into a variable so that
190 // the function is NOT called more than once per iteration
191 const std::size_t elem_key = key(*it);
192
193 mem.output[mem.count[elem_key]] = std::move(*(it++));
194 ++mem.count[elem_key];
195 }
196
197 // calculate output
198 if constexpr (is_increasing) {
199 auto it = begin;
200 for (std::size_t k = 0; k < actual_container_size;) {
201 *(it++) = std::move(mem.output[k++]);
202 }
203 }
204 else {
205 auto it = begin;
206 for (std::size_t k = actual_container_size - 1; k > 0;) {
207 *(it++) = std::move(mem.output[k--]);
208 }
209 *it = std::move(mem.output[0]);
210 }
211}
212
241template <
242 typename value_t,
243 typename sort_type,
244 typename value_iterator_t,
245 std::enable_if_t<
246 is_pointer_iterator_v<value_t, value_iterator_t> &&
247 (
248 std::is_same_v<sort_type, non_decreasing_t> ||
249 std::is_same_v<sort_type, non_increasing_t>
250 ),
251 bool
252 > = true
253>
255 const value_iterator_t begin, const value_iterator_t end,
256 const std::size_t largest_key,
257 const std::size_t upper_bound_size,
258 const std::function<std::size_t (const value_t&)>& key
259)
260noexcept
261{
262 // nothing to do if there are no elements to sort
263 if (begin == end) { return; }
264
265 countingsort::memory<value_t> mem(largest_key+1, upper_bound_size);
266
267 counting_sort<value_t, sort_type, false, value_iterator_t>
268 (begin, end, largest_key+1, key, mem);
269}
270
271} // -- namespace sorting
272} // -- namespace detail
273} // -- namespace lal
void counting_sort(const value_iterator_t begin, const value_iterator_t end, const std::size_t largest_key_plus_1, const std::function< std::size_t(const value_t &)> &key, countingsort::memory< value_t > &mem) noexcept
Counting sort algorithm with reusable memory.
Definition: counting_sort.hpp:155
Main namespace of the library.
Definition: basic_types.hpp:50
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59
void fill(const T &v) noexcept
Assign the same value to every element in the data.
Definition: data_array.hpp:263
Memory used for the counting sort algorithm.
Definition: counting_sort.hpp:72
void reset_count() noexcept
Set the count member to 0.
Definition: counting_sort.hpp:107
~memory() noexcept=default
Destructor.
data_array< T > output
The output array.
Definition: counting_sort.hpp:76
memory() noexcept=default
Constructor.
data_array< std::size_t > count
Amount of times the key of an element occurs.
Definition: counting_sort.hpp:74