Mercurial > lbo > hg > ccplay
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;