mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 22:50:38 +03:00
Migrate some heap operations to std.algorithm
This commit is contained in:
parent
cc77356a9d
commit
b97a6c2e7e
2 changed files with 20 additions and 71 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue