[PATCH] [libc++] Fix std::make_heap's worst case time complexity
Richard Smith
richard at metafoo.co.uk
Tue Jul 15 14:37:34 PDT 2014
+ while (__first + __child < __last)
This is invalid when __first + __child > __last. Instead, use:
while (__child < __last - __first)
Likewise for later iterator additions.
+ if ((__first + __child + 1) < __last &&
+ __comp(*(__first + __child), *(__first + __child + 1)))
+ // right-child exists and is greater than left-child
+ ++__child;
+
+ // check if we are in heap-order
+ if (__comp(*(__first + __child), *(__first + __start)))
+ // we are, __start is larger than it's largest child
+ break;
This is slightly inefficient. Instead of computing left < right and then
computing start < max(left, right), you can compute start < left and start
< right, and save a comparison whenever start < left.
+ // we are not in heap-order, swap the parent with it's largest
child
Typo "it's".
+ swap(*(__first + __child), *(__first + __start));
This is inefficient: a swap is typically 3 moves, which is more than you
need here. I think you should do what Howard's code did: rotate the loop so
you first determine whether any elements need to move, and if they do, move
the parent into a local variable, move each element over its parent instead
of swapping, and drop the parent into the right spot at the end.
+ // recompute the child based off of the updated parent
"recompute the first child of the updated parent"?
Having a __push_heap_back and a __sift_down seems weird to me. I think we
should either have __sift_down and __sift_up or __push_heap_back and
__push_heap_front (and I prefer the __sift names because we're not
necessarily pushing at the front any more). Is there a reason to give these
different names?
On Tue, Jul 15, 2014 at 12:18 PM, David Majnemer <david.majnemer at gmail.com>
wrote:
> Ping.
>
> On Wed, Jul 9, 2014 at 3:14 AM, David Majnemer <david.majnemer at gmail.com>
> wrote:
> > std::make_heap is currently implemented by iteratively applying a
> > sift_up-type algorithm.
> > Since sift-up is O(ln n), this gives std::make_heap a worst case time
> > complexity of O(n ln n). Since the C++ standard mandates that
> > std::make_heap make no more than O(3n) comparisons, this makes our
> > std::make_heap out of spec.
> >
> > Fix this by introducing an implementation of __sift_down and switch
> > std::make_heap to create the heap using it. This gives std::make_heap
> > linear time complexity in the worst case.
> >
> > This fixes PR20161.
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140715/b666aef7/attachment.html>
More information about the cfe-commits
mailing list