Migrate some heap operations to std.algorithm

This commit is contained in:
Xinok 2015-07-08 11:18:01 -05:00
parent cc77356a9d
commit b97a6c2e7e
2 changed files with 20 additions and 71 deletions

View file

@ -1123,7 +1123,7 @@ private void quickSortImpl(alias less, Range)(Range r, size_t depth)
{
if (depth == 0)
{
HeapSortImpl!(less, Range).heapSort(r);
HeapOps!(less, Range).heapSort(r);
return;
}
depth = depth >= depth.max / 2 ? (depth / 3) * 2 : (depth * 2) / 3;
@ -1167,8 +1167,8 @@ private void quickSortImpl(alias less, Range)(Range r, size_t depth)
}
}
// Bottom-Up Heap-Sort Implementation
private template HeapSortImpl(alias less, Range)
// Heap operations for random-access ranges
package(std) template HeapOps(alias less, Range)
{
import std.algorithm.mutation : swapAt;
@ -1185,21 +1185,27 @@ private template HeapSortImpl(alias less, Range)
if(r.length < 2) return;
// Build Heap
size_t i = r.length / 2;
while(i > 0) sift(r, --i, r.length);
heapify(r);
// Sort
i = r.length - 1;
size_t i = r.length - 1;
while(i > 0)
{
swapAt(r, 0, i);
sift(r, 0, i);
percolate(r, 0, i);
--i;
}
}
//template because of @@@12410@@@
void sift()(Range r, size_t parent, immutable size_t end)
void heapify()(Range r)
{
size_t i = r.length / 2;
while(i > 0) percolate(r, --i, r.length);
}
//template because of @@@12410@@@
void percolate()(Range r, size_t parent, immutable size_t end)
{
immutable root = parent;
size_t child = void;

View file

@ -59,9 +59,12 @@ if (isRandomAccessRange!(Store) || isRandomAccessRange!(typeof(Store.init[])))
{
import std.functional : binaryFun;
import std.exception : enforce;
import std.algorithm : move, min;
import std.algorithm : move, min, HeapOps, swapAt;
import std.typecons : RefCounted, RefCountedAutoInitialize;
alias percolate = HeapOps!(less, Store).percolate;
alias heapify = HeapOps!(less, Store).heapify;
// Really weird @@BUG@@: if you comment out the "private:" label below,
// std.algorithm can't unittest anymore
//private:
@ -103,40 +106,6 @@ if (isRandomAccessRange!(Store) || isRandomAccessRange!(typeof(Store.init[])))
}
}
// Assuming the element at "parent" perturbs the heap property in
// store r, percolates it down the heap such that the heap
// property is restored.
private void percolate(Store r, size_t parent, immutable size_t end)
{
immutable root = parent;
size_t child = void;
// Sift down
for (;;)
{
child = parent * 2 + 1;
if (child >= end) break;
if (child + 1 < end && comp(r[child], r[child + 1])) child += 1;
swap(r, parent, child);
parent = child;
}
child = parent;
// Sift up
while (child > root)
{
parent = (child - 1) / 2;
if (comp(r[parent], r[child]))
{
swap(r, parent, child);
child = parent;
}
else break;
}
}
// @@@BUG@@@: add private here, std.algorithm doesn't unittest anymore
/*private*/ void pop(Store store)
{
@ -149,28 +118,6 @@ if (isRandomAccessRange!(Store) || isRandomAccessRange!(typeof(Store.init[])))
percolate(store, 0, store.length - 1);
}
/*private*/ static void swap(Store _store, size_t i, size_t j)
{
static if (is(typeof(swap(_store[i], _store[j]))))
{
swap(_store[i], _store[j]);
}
else static if (is(typeof(_store.moveAt(i))))
{
auto t1 = _store.moveAt(i);
auto t2 = _store.moveAt(j);
_store[i] = move(t2);
_store[j] = move(t1);
}
else // assume it's a container and access its range with []
{
auto t1 = _store[].moveAt(i);
auto t2 = _store[].moveAt(j);
_store[i] = move(t2);
_store[j] = move(t1);
}
}
public:
/**
@ -196,11 +143,7 @@ the heap work incorrectly.
_store = move(s);
_length = min(_store.length, initialSize);
if (_length < 2) return;
for (auto i = (_length - 2) / 2; ; )
{
this.percolate(_store, i, _length);
if (i-- == 0) break;
}
heapify(s);
assertValid();
}
@ -330,7 +273,7 @@ and $(D length == capacity), throws an exception.
auto parentIdx = (n - 1) / 2;
if (!comp(_store[parentIdx], _store[n])) break; // done!
// must swap and continue
swap(_store, parentIdx, n);
swapAt(_store, parentIdx, n);
n = parentIdx;
}
++_length;