Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion libc/src/stdlib/qsort_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,15 @@ class Array {
size_t size() const { return array_size; }

// Make an Array starting at index |i| and size |s|.
Array make_array(size_t i, size_t s) const {
LIBC_INLINE Array make_array(size_t i, size_t s) const {
return Array(get(i), s, elem_size, compare);
}

// Reset this Array to point at a different interval of the same items.
LIBC_INLINE void reset_bounds(uint8_t *a, size_t s) {
array = a;
array_size = s;
}
};

using SortingRoutine = void(const Array &);
Expand Down
37 changes: 26 additions & 11 deletions libc/src/stdlib/quick_sort.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace LIBC_NAMESPACE_DECL {
namespace internal {

// A simple quicksort implementation using the Hoare partition scheme.
static size_t partition(const Array &array) {
LIBC_INLINE size_t partition(const Array &array) {
const size_t array_size = array.size();
size_t pivot_index = array_size / 2;
uint8_t *pivot = array.get(pivot_index);
Expand Down Expand Up @@ -59,17 +59,32 @@ static size_t partition(const Array &array) {
}
}

LIBC_INLINE void quick_sort(const Array &array) {
const size_t array_size = array.size();
if (array_size <= 1)
return;
size_t split_index = partition(array);
if (array_size <= 2) {
// The partition operation sorts the two element array.
return;
LIBC_INLINE void quick_sort(Array array) {
while (true) {
const size_t array_size = array.size();
if (array_size <= 1)
return;
size_t split_index = partition(array);
if (array_size == 2)
// The partition operation sorts the two element array.
return;

// Make Arrays describing the two sublists that still need sorting.
Array left = array.make_array(0, split_index);
Array right = array.make_array(split_index, array.size() - split_index);

// Recurse to sort the smaller of the two, and then loop round within this
// function to sort the larger. This way, recursive call depth is bounded
// by log2 of the total array size, because every recursive call is sorting
// a list at most half the length of the one in its caller.
if (left.size() < right.size()) {
quick_sort(left);
array.reset_bounds(right.get(0), right.size());
} else {
quick_sort(right);
array.reset_bounds(left.get(0), left.size());
}
}
quick_sort(array.make_array(0, split_index));
quick_sort(array.make_array(split_index, array.size() - split_index));
}

} // namespace internal
Expand Down
Loading