I’ve written the following code but it doesn’t give the correct result (for instance if you enter [-1,-1], it returns [-1,-1,-1].
import std.stdio, std.range, std.container, std.algorithm;
DList!T strandSort(T)(DList!T list) {
static DList!T merge(DList!T left, DList!T right) {
DList!T res;
while (!left.empty && !right.empty) {
if (left.front <= right.front) {
res.insertBack(left.front);
left.removeFront();
} else {
res.insertBack(right.front);
right.removeFront();
}
}
res.insertBack(left[]);
res.insertBack(right[]);
return res;
}
DList!T result, sorted;
while (!list.empty) {
sorted.clear();
sorted.insertBack(list.front);
list.removeFront();
foreach (item; list) {
if (sorted.back <= item) {
sorted.insertBack(item);
list.stableLinearRemove(list[].find(item).take(1)));
}
}
result = merge(sorted, result);
}
return result;
}
void main() {
auto lst = DList!int([-1,-1]);
foreach (e; strandSort(lst))
writef("%d ", e);
}
Sometimes, the stableLinearRemove doesn’t remove the item from the list. The question is, is it a bug in my code, or in Phobos?
See also the discusion on Rosettacode.org
Edit: I suspect it’s caused by removeFront. It doesn’t set the prev node pointer of the second node to null when the first node is removed. When the item to be removed from the list by linearRemove happens to be the first node, it won’t be removed. The remove function checks “before” and “after” nodes and the “before” is still set. If I write it like this, it does work:
if (sorted.back <= item) {
sorted.insertBack(item);
if (list.front == item)
list.removeFront();
else
list.stableLinearRemove(list[].find(item).take(1)));
}
I don’t think it’s a bug in Phobos, but rather a gotcha. You shouldn’t rely on linearRemove to remove an element if it might be the first in the list. Check for that first and use removeFront. Is also more efficient.
In the case above, a better solution would be to copy the list: