changeset 3:86e76ae3ac8a

sorting: heap
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 07 Mar 2023 01:14:02 +0100
parents ed80bcd28852
children bb5c00d28022
files CMakeLists.txt cclib.cc sorting.cc
diffstat 3 files changed, 105 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Mon Mar 06 10:13:49 2023 +0100
+++ b/CMakeLists.txt	Tue Mar 07 01:14:02 2023 +0100
@@ -14,3 +14,5 @@
 ADD_EXECUTABLE(cclib cclib.cc)
 TARGET_LINK_LIBRARIES(cclib exec)
 
+ADD_EXECUTABLE(sorting sorting.cc)
+TARGET_LINK_LIBRARIES(sorting exec)
--- a/cclib.cc	Mon Mar 06 10:13:49 2023 +0100
+++ b/cclib.cc	Tue Mar 07 01:14:02 2023 +0100
@@ -1,3 +1,4 @@
+#include <algorithm>
 #include <any>
 #include <array>
 #include <iostream>
@@ -9,6 +10,28 @@
 
 using namespace std;
 
+constexpr vector<int> get_default_vector(void) {
+    vector<int> v{1,15,25,35,45,65};
+    auto mid = find(v.begin(), v.end(), 35);
+    vector<int> v2(v.begin(), mid+1);
+    copy(v2.begin(), v2.end(), back_inserter(v));
+    return v;
+}
+
+template<typename It>
+void print_container(It begin, const It& end) {
+    do {
+        cout << *begin++ << " ";
+    } while (begin != end);
+    cout << endl;
+}
+
+void test_constexpr_functions(void) {
+    auto v = get_default_vector();
+    cout << v.size() << endl;
+    print_container(v.begin(), v.end());
+}
+
 void test_any_copy(void) {
     int i = 10;
     any a1(i);
@@ -57,6 +80,8 @@
         test_span();
     else if (task == "test_regex")
         test_regex();
+    else if (task == "test_constexpr_functions")
+        test_constexpr_functions();
 
     return 0;
 }
--- a/sorting.cc	Mon Mar 06 10:13:49 2023 +0100
+++ b/sorting.cc	Tue Mar 07 01:14:02 2023 +0100
@@ -1,11 +1,13 @@
 #include <cassert>
 
 #include <algorithm>
+#include <functional>
 #include <iostream>
 #include <string>
+#include <utility>
 #include <vector>
 
-using std::vector, std::string;
+using namespace std;
 
 template<typename T>
 int partition(vector<T>& v, int left, int right) {
@@ -107,14 +109,87 @@
         }
         return hi;
     }
+    return end;
 }
 
+pair<size_t, size_t> heap_children(size_t i) {
+    return make_pair(2*i+1, 2*i+2);
+}
+
+template<typename T> void heap_sift_down(vector<T>& v, size_t i) {
+    if (i >= v.size())
+        return;
+
+    pair<size_t, size_t> children = heap_children(i);
+
+    // Special check if we are down in the tree.
+    if (get<0>(children) >= v.size())
+        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));
+        return;
+    }
+
+    T& left = v.at(get<0>(children)), &right = v.at(get<1>(children));
+    // Order already correct.
+    if (max(left, right) < v.at(i))
+        return;
+
+    // Recur:
+    if (left > right) {
+        swap(v.at(i), left);
+        heap_sift_down(v, get<0>(children));
+    } else {
+        swap(v.at(i), right);
+        heap_sift_down(v, get<1>(children));
+    }
+}
+
+template<typename T> void heap_sift_up(vector<T>& v, size_t i) {
+    if (i == 0 || i >= v.size())
+        return;
+
+    size_t parent_ix = (i-1)/2;
+    T& parent = v.at(parent_ix);
+    T& current = v.at(i);
+
+    if (parent < current) {
+        swap(parent, current);
+        heap_sift_up(v, parent_ix);
+    }
+}
+
+enum class SiftDirection { Up, Down };
+
+/// Build max-heap by sifting-down.
+template<typename T>
+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);
+        }
+    else
+        for (size_t i = 0; i < v.size(); i++) {
+                heap_sift_up(v, i);
+        }
+}
+
+// Build max heap by sifting-up
+
 int main(void) {
     vector<string> v{"hello", "olleh", "abc", "bca", "world", "wrlod"};
+    vector<int> vi{1,2,3,4,5,6,7,8,9,10};
 
-    std::cout << shifted_binary_search({5,6,1,2,3}, 1) << "\n";
+    // vi:
+    // 10
+    // ->             9                     7
+    // ->        8          5        6           3
+    // ->    1       4    2    x   x   x       x    x
+    make_into_heap(vi, SiftDirection::Up);
 
-    for (const auto& a : v)
+    for (const auto& a : vi)
         std::cout << a << " ";
     std::cout << "\n";
     return 0;