mirror of
https://github.com/dlang/phobos.git
synced 2025-05-01 07:30:33 +03:00
Improved siftDown and percolate, also documented both
This commit is contained in:
parent
96ece512a2
commit
01bdccf310
1 changed files with 44 additions and 24 deletions
|
@ -1277,15 +1277,18 @@ package(std) template HeapOps(alias less, Range)
|
||||||
for (size_t i = r.length - 1; i > 0; --i)
|
for (size_t i = r.length - 1; i > 0; --i)
|
||||||
{
|
{
|
||||||
r.swapAt(0, i);
|
r.swapAt(0, i);
|
||||||
siftDown(r, 0, i);
|
percolate(r, 0, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//template because of @@@12410@@@
|
//template because of @@@12410@@@
|
||||||
void buildHeap()(Range r)
|
void buildHeap()(Range r)
|
||||||
{
|
{
|
||||||
size_t i = r.length / 2;
|
immutable n = r.length;
|
||||||
while (i-- > 0) siftDown(r, i, r.length);
|
for (size_t i = n / 2; i-- > 0; )
|
||||||
|
{
|
||||||
|
siftDown(r, i, n);
|
||||||
|
}
|
||||||
assert(isHeap(r));
|
assert(isHeap(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1301,53 +1304,70 @@ package(std) template HeapOps(alias less, Range)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//template because of @@@12410@@@
|
// Sifts down r[parent] (which is initially assumed to be messed up) so the
|
||||||
|
// heap property is restored for r[parent .. end].
|
||||||
|
// template because of @@@12410@@@
|
||||||
void siftDown()(Range r, size_t parent, immutable size_t end)
|
void siftDown()(Range r, size_t parent, immutable size_t end)
|
||||||
{
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
auto child = parent * 2 + 1;
|
auto child = (parent + 1) * 2;
|
||||||
if (child >= end) break;
|
if (child >= end)
|
||||||
auto child1 = child + 1;
|
{
|
||||||
if (child1 < end && lessFun(r[child], r[child1])) child = child1;
|
// Leftover left child?
|
||||||
|
if (child == end && lessFun(r[parent], r[--child]))
|
||||||
|
r.swapAt(parent, child);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto leftChild = child - 1;
|
||||||
|
if (lessFun(r[child], r[leftChild])) child = leftChild;
|
||||||
if (!lessFun(r[parent], r[child])) break;
|
if (!lessFun(r[parent], r[child])) break;
|
||||||
r.swapAt(parent, child);
|
r.swapAt(parent, child);
|
||||||
parent = child;
|
parent = child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Alternate version of siftDown that performs fewer comparisons, see
|
||||||
|
// https://en.wikipedia.org/wiki/Heapsort#Bottom-up_heapsort. The percolate
|
||||||
|
// process first sifts the parent all the way down (without comparing it
|
||||||
|
// against the leaves), and then a bit up until the heap property is
|
||||||
|
// restored. So there are more swaps but fewer comparisons. Gains are made
|
||||||
|
// when the final position is likely to end toward the bottom of the heap,
|
||||||
|
// so not a lot of sifts back are performed.
|
||||||
//template because of @@@12410@@@
|
//template because of @@@12410@@@
|
||||||
void percolate()(Range r, size_t parent, immutable size_t end)
|
void percolate()(Range r, size_t parent, immutable size_t end)
|
||||||
{
|
{
|
||||||
immutable root = parent;
|
immutable root = parent;
|
||||||
size_t child = void;
|
|
||||||
|
|
||||||
// Sift down
|
// Sift down
|
||||||
while(true)
|
for (;;)
|
||||||
{
|
{
|
||||||
child = parent * 2 + 1;
|
auto child = (parent + 1) * 2;
|
||||||
|
|
||||||
if(child >= end) break;
|
if (child >= end)
|
||||||
|
{
|
||||||
auto child1 = child + 1;
|
if (child == end)
|
||||||
if (child1 < end && lessFun(r[child], r[child1])) child = child1;
|
{
|
||||||
|
// Leftover left node.
|
||||||
|
--child;
|
||||||
|
r.swapAt(parent, child);
|
||||||
|
parent = child;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto leftChild = child - 1;
|
||||||
|
if (lessFun(r[child], r[leftChild])) child = leftChild;
|
||||||
r.swapAt(parent, child);
|
r.swapAt(parent, child);
|
||||||
parent = child;
|
parent = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
child = parent;
|
|
||||||
|
|
||||||
// Sift up
|
// Sift up
|
||||||
while(child > root)
|
for (auto child = parent; child > root; child = parent)
|
||||||
{
|
{
|
||||||
parent = (child - 1) / 2;
|
parent = (child - 1) / 2;
|
||||||
if(lessFun(r[parent], r[child]))
|
if (!lessFun(r[parent], r[child])) break;
|
||||||
{
|
r.swapAt(parent, child);
|
||||||
r.swapAt(parent, child);
|
|
||||||
child = parent;
|
|
||||||
}
|
|
||||||
else break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue