changeset 21:ae1327f0f99f

Improve heapsort
author Lewin Bormann <lbo@spheniscida.de>
date Fri, 07 Apr 2023 15:50:41 +0200
parents ecc574aa2021
children 68cf11026c57
files sorting.cc
diffstat 1 files changed, 27 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/sorting.cc	Fri Apr 07 15:13:48 2023 +0200
+++ b/sorting.cc	Fri Apr 07 15:50:41 2023 +0200
@@ -5,6 +5,8 @@
 #include <algorithm>
 #include <functional>
 #include <iostream>
+#include <ranges>
+#include <span>
 #include <string>
 #include <utility>
 #include <vector>
@@ -119,7 +121,7 @@
     return make_pair(2*i+1, 2*i+2);
 }
 
-template<typename T> void heap_sift_down(vector<T>& v, size_t i) {
+template<typename T> void heap_sift_down(span<T> v, size_t i) {
     if (i >= v.size())
         return;
 
@@ -130,22 +132,22 @@
         return;
     else if (get<1>(children) >= v.size()) {
         size_t left = get<0>(children);
-        T& target = v.at(i) > v.at(left) ? v.at(i) : v.at(left);
-        swap(target, v.at(i));
+        T& target = v[i] > v[left] ? v[i] : v[left];
+        swap(target, v[i]);
         return;
     }
 
-    T& left = v.at(get<0>(children)), &right = v.at(get<1>(children));
+    T& left = v[get<0>(children)], &right = v[get<1>(children)];
     // Order already correct.
-    if (max(left, right) < v.at(i))
+    if (max(left, right) < v[i])
         return;
 
     // Recur:
     if (left > right) {
-        swap(v.at(i), left);
+        swap(v[i], left);
         heap_sift_down(v, get<0>(children));
     } else {
-        swap(v.at(i), right);
+        swap(v[i], right);
         heap_sift_down(v, get<1>(children));
     }
 }
@@ -170,7 +172,7 @@
 void make_into_heap(vector<T>& v, SiftDirection direction = SiftDirection::Down) {
     if (direction == SiftDirection::Down)
         for (ssize_t i = v.size()-1; i >= 0; i--) {
-                heap_sift_down(v, i);
+                heap_sift_down(span(v), i);
         }
     else
         for (size_t i = 0; i < v.size(); i++) {
@@ -179,11 +181,27 @@
 }
 
 
+template<typename T>
+void flatten_heap(vector<T>& v) {
+    for (int i = v.size()-1; i > 0; i--) {
+        swap(v[0], v[i]);
+        heap_sift_down(span(v.begin(), v.begin()+i), 0);
+    }
+}
+
+//template<typename T, typename R> requires (range<R> and is_same<range_value_t<R>, T>)
+template<typename T>
+void heap_sort(vector<T>& rng) {
+    make_into_heap(rng);
+    flatten_heap(rng);
+    return;
+}
+
 int main(void) {
     vector<string> v{"hello", "olleh", "abc", "bca", "world", "wrlod"};
     vector<int> vi{5,5,6,1,3,2,5,8,9};
 
-    timeit_f([&vi]() -> void { quicksort(vi); }, "quicksort");
+    timeit_f([&vi]() { heap_sort(vi); }, "heapsort");
     fmt::print("{}\n", vi);
     return 0;
 }