snippetcppMinor
C++ Heap Sort Implementation
Viewed 0 times
sortimplementationheap
Problem
Just checking if I could still do it:
#include
#include
std::size_t getParent(std::size_t n)
{
return (n - 1) / 2;
}
template
void heapify(I begin, I end)
{
std::size_t size = std::distance(begin, end);
for(std::size_t loop = 1;loop
void heapPop(I begin, I end)
{
I last = end - 1;
std::swap(*begin, *last);
std::size_t size = std::distance(begin, last);
std::size_t current = 0;
while(current *(begin + child2)) ? child1 : child2;
}
else if (child1
void heap_sort(I begin, I end)
{
heapify(begin, end);
while(begin != end)
{
heapPop(begin, end);
--end;
}
}
int main()
{
int data[] = {6,5,3,1,8,7,2,4};
heap_sort(std::begin(data), std::end(data));
std::copy(std::begin(data), std::end(data), std::ostream_iterator(std::cout, ", "));
std::cout << "\n";
}Solution
The
You just need the sinking logic that you already implemented. But instead of having current always starting at 0 you can set it as a parameter:
Due to the fact that the elements are leafs you can ignore them, so you just need to apply sink
times to build the heap:
Alternative sink implementation:
IMO this implementation is more concise:
heapify and parentfunctions can be avoided:You just need the sinking logic that you already implemented. But instead of having current always starting at 0 you can set it as a parameter:
template
void sink(I begin, I end, std::size_t index)
{
std::size_t size = std::distance(begin, end);
std::size_t current = index;
while (current *(begin + child2)) ? child1 : child2;
}
else if (child1 < size)
{
goodChild = child1;
}
if (*(begin + current) < *(begin + goodChild))
{
std::swap(*(begin + current), *(begin + goodChild));
current = goodChild;
continue;
}
break;
}
}Due to the fact that the elements are leafs you can ignore them, so you just need to apply sink
times to build the heap:
template
void heap_sort(I begin, I end)
{
std::size_t size = std::distance(begin, end);
for (int i = size / 2 - 1; i > -1; --i)
{
sink(begin, end, i);
}
while (begin != --end)
{
std::swap(*begin, *end);
sink(begin, end, 0);
}
}Alternative sink implementation:
IMO this implementation is more concise:
template
void sink(I begin, I end, std::size_t index)
{
std::size_t size = std::distance(begin, end);
std::size_t current = index;
std::size_t child;
std::less less;
while ((child = 2 * current + 1) < size)
{
I itr_child = begin + child;
I itr_current = begin + current;
if(child < size - 1
&& less(*itr_child, *(itr_child + 1))
{
++itr_child;
}
if (!less(*itr_current, *itr_child))
{
break;
}
std::swap(*itr_current, *itr_child);
current = child;
}
}Code Snippets
template<typename I>
void sink(I begin, I end, std::size_t index)
{
std::size_t size = std::distance(begin, end);
std::size_t current = index;
while (current < size)
{
std::size_t child1 = current * 2 + 1;
std::size_t child2 = current * 2 + 2;
std::size_t goodChild = current;
if (child2 < size)
{
goodChild = (*(begin + child1) > *(begin + child2)) ? child1 : child2;
}
else if (child1 < size)
{
goodChild = child1;
}
if (*(begin + current) < *(begin + goodChild))
{
std::swap(*(begin + current), *(begin + goodChild));
current = goodChild;
continue;
}
break;
}
}template<typename I>
void heap_sort(I begin, I end)
{
std::size_t size = std::distance(begin, end);
for (int i = size / 2 - 1; i > -1; --i)
{
sink(begin, end, i);
}
while (begin != --end)
{
std::swap(*begin, *end);
sink(begin, end, 0);
}
}template<typename I>
void sink(I begin, I end, std::size_t index)
{
std::size_t size = std::distance(begin, end);
std::size_t current = index;
std::size_t child;
std::less<decltype(*begin)> less;
while ((child = 2 * current + 1) < size)
{
I itr_child = begin + child;
I itr_current = begin + current;
if(child < size - 1
&& less(*itr_child, *(itr_child + 1))
{
++itr_child;
}
if (!less(*itr_current, *itr_child))
{
break;
}
std::swap(*itr_current, *itr_child);
current = child;
}
}Context
StackExchange Code Review Q#130064, answer score: 3
Revisions (0)
No revisions yet.