1a6d2da8bSlntue //===-- Implementation of heap sort -----------------------------*- C++ -*-===// 2a6d2da8bSlntue // 3a6d2da8bSlntue // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a6d2da8bSlntue // See https://llvm.org/LICENSE.txt for license information. 5a6d2da8bSlntue // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a6d2da8bSlntue // 7a6d2da8bSlntue //===----------------------------------------------------------------------===// 8a6d2da8bSlntue 9a6d2da8bSlntue #ifndef LLVM_LIBC_SRC_STDLIB_HEAP_SORT_H 10a6d2da8bSlntue #define LLVM_LIBC_SRC_STDLIB_HEAP_SORT_H 11a6d2da8bSlntue 12a6d2da8bSlntue #include "src/__support/CPP/cstddef.h" 13a6d2da8bSlntue #include "src/stdlib/qsort_data.h" 14a6d2da8bSlntue 15a6d2da8bSlntue namespace LIBC_NAMESPACE_DECL { 16a6d2da8bSlntue namespace internal { 17a6d2da8bSlntue 18a6d2da8bSlntue // A simple in-place heapsort implementation. 19a6d2da8bSlntue // Follow the implementation in https://en.wikipedia.org/wiki/Heapsort. 20a6d2da8bSlntue 21*a738d81cSLukas Bergdoll template <typename A, typename F> 22*a738d81cSLukas Bergdoll LIBC_INLINE void heap_sort(const A &array, const F &is_less) { 23*a738d81cSLukas Bergdoll size_t end = array.len(); 24a6d2da8bSlntue size_t start = end / 2; 25a6d2da8bSlntue 26*a738d81cSLukas Bergdoll const auto left_child = [](size_t i) -> size_t { return 2 * i + 1; }; 27a6d2da8bSlntue 28a6d2da8bSlntue while (end > 1) { 29a6d2da8bSlntue if (start > 0) { 30a6d2da8bSlntue // Select the next unheapified element to sift down. 31a6d2da8bSlntue --start; 32a6d2da8bSlntue } else { 33a6d2da8bSlntue // Extract the max element of the heap, moving a leaf to root to be sifted 34a6d2da8bSlntue // down. 35a6d2da8bSlntue --end; 36a6d2da8bSlntue array.swap(0, end); 37a6d2da8bSlntue } 38a6d2da8bSlntue 39a6d2da8bSlntue // Sift start down the heap. 40a6d2da8bSlntue size_t root = start; 41a6d2da8bSlntue while (left_child(root) < end) { 42a6d2da8bSlntue size_t child = left_child(root); 43a6d2da8bSlntue // If there are two children, set child to the greater. 44*a738d81cSLukas Bergdoll if ((child + 1 < end) && is_less(array.get(child), array.get(child + 1))) 45a6d2da8bSlntue ++child; 46a6d2da8bSlntue 47a6d2da8bSlntue // If the root is less than the greater child 48*a738d81cSLukas Bergdoll if (!is_less(array.get(root), array.get(child))) 49a6d2da8bSlntue break; 50a6d2da8bSlntue 51a6d2da8bSlntue // Swap the root with the greater child and continue sifting down. 52a6d2da8bSlntue array.swap(root, child); 53a6d2da8bSlntue root = child; 54a6d2da8bSlntue } 55a6d2da8bSlntue } 56a6d2da8bSlntue } 57a6d2da8bSlntue 58a6d2da8bSlntue } // namespace internal 59a6d2da8bSlntue } // namespace LIBC_NAMESPACE_DECL 60a6d2da8bSlntue 61a6d2da8bSlntue #endif // LLVM_LIBC_SRC_STDLIB_HEAP_SORT_H 62