diff --git a/BAN/include/BAN/Heap.h b/BAN/include/BAN/Heap.h new file mode 100644 index 00000000..f2322738 --- /dev/null +++ b/BAN/include/BAN/Heap.h @@ -0,0 +1,90 @@ +#pragma once + +#include +#include +#include +#include + +namespace BAN +{ + + namespace detail + { + + template + void heapify_up(It begin, size_t index, Comp comp) + { + size_t parent = (index - 1) / 2; + while (parent < index) + { + if (comp(*(begin + index), *(begin + parent))) + break; + swap(*(begin + parent), *(begin + index)); + index = parent; + parent = (index - 1) / 2; + } + } + + template + void heapify_down(It begin, size_t index, size_t len, Comp comp) + { + for (;;) + { + const size_t lchild = 2 * index + 1; + const size_t rchild = 2 * index + 2; + + size_t child = 0; + if (lchild < len && !comp(*(begin + lchild), *(begin + index))) + { + if (rchild < len && !comp(*(begin + rchild), *(begin + lchild))) + child = rchild; + else + child = lchild; + } + else if (rchild < len && !comp(*(begin + rchild), *(begin + index))) + child = rchild; + else + break; + + swap(*(begin + child), *(begin + index)); + index = child; + } + } + + } + + template>> + void make_heap(It begin, It end, Comp comp = {}) + { + const size_t len = distance(begin, end); + if (len <= 1) + return; + + size_t index = (len - 2) / 2; + while (index < len) + detail::heapify_down(begin, index--, len, comp); + } + + template>> + void push_heap(It begin, It end, Comp comp = {}) + { + const size_t len = distance(begin, end); + detail::heapify_up(begin, len - 1, comp); + } + + template>> + void pop_heap(It begin, It end, Comp comp = {}) + { + const size_t len = distance(begin, end); + swap(*begin, *(begin + len - 1)); + detail::heapify_down(begin, 0, len - 1, comp); + } + + template>> + void sort_heap(It begin, It end, Comp comp = {}) + { + while (begin != end) + pop_heap(begin, end--, comp); + } + +} diff --git a/BAN/include/BAN/Sort.h b/BAN/include/BAN/Sort.h index d50c6204..4f3a3d7a 100644 --- a/BAN/include/BAN/Sort.h +++ b/BAN/include/BAN/Sort.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -67,82 +68,6 @@ namespace BAN::sort } } - namespace detail - { - - template - void push_heap(It begin, size_t hole_index, size_t top_index, it_value_type_t value, Comp comp) - { - size_t parent = (hole_index - 1) / 2; - while (hole_index > top_index && comp(*next(begin, parent), value)) - { - *next(begin, hole_index) = move(*next(begin, parent)); - hole_index = parent; - parent = (hole_index - 1) / 2; - } - *next(begin, hole_index) = move(value); - } - - template - void adjust_heap(It begin, size_t hole_index, size_t len, it_value_type_t value, Comp comp) - { - const size_t top_index = hole_index; - size_t child = hole_index; - while (child < (len - 1) / 2) - { - child = 2 * (child + 1); - if (comp(*next(begin, child), *next(begin, child - 1))) - child--; - *next(begin, hole_index) = move(*next(begin, child)); - hole_index = child; - } - if (len % 2 == 0 && child == (len - 2) / 2) - { - child = 2 * (child + 1); - *next(begin, hole_index) = move(*next(begin, child - 1)); - hole_index = child - 1; - } - push_heap(begin, hole_index, top_index, move(value), comp); - } - - } - - template> - void make_heap(It begin, It end, Comp comp = {}) - { - const size_t len = distance(begin, end); - if (len <= 1) - return; - - size_t parent = (len - 2) / 2; - while (true) - { - detail::adjust_heap(begin, parent, len, move(*next(begin, parent)), comp); - - if (parent == 0) - break; - - parent--; - } - } - - template>> - void sort_heap(It begin, It end, Comp comp = {}) - { - const size_t len = distance(begin, end); - if (len <= 1) - return; - - size_t last = len; - while (last > 1) - { - last--; - typename It::value_type x = move(*next(begin, last)); - *next(begin, last) = move(*begin); - detail::adjust_heap(begin, 0, last, move(x), comp); - } - } - template>> void heap_sort(It begin, It end, Comp comp = {}) {