Jump to page: 1 2 3
Thread overview
Heap: container or range?
Jan 30, 2009
Daniel Keep
Jan 30, 2009
Bill Baxter
Jan 30, 2009
Bill Baxter
Jan 30, 2009
Bill Baxter
Jan 30, 2009
Christopher Wright
Jan 30, 2009
Jason House
Jan 30, 2009
Sean Kelly
Jan 30, 2009
Sean Kelly
Jan 30, 2009
Brad Roberts
Jan 30, 2009
Denis Koroskin
Jan 30, 2009
Sean Kelly
Jan 30, 2009
Sergey Gromov
Jan 30, 2009
Denis Koroskin
Jan 30, 2009
Brad Roberts
Jan 31, 2009
Derek Parnell
Jan 30, 2009
BCS
Jan 30, 2009
Yigal Chripun
Jan 30, 2009
Bill Baxter
Jan 30, 2009
Yigal Chripun
Jan 30, 2009
Don
January 30, 2009
A "computer science heap" is a structure that offers fast access to the largest element and fast extraction of it (which in turn provides access to the next largest element etc.).

I'm just done working on the heap in std.algorithm. Now, it turns out that heap supports both a meaningful definition as a full-fledged container, and a beautiful definition as a range.

If Heap is a range, you initiate it with another range, which Heap organizes in the heap manner. Then, successive calls to next() nicely extract elements starting from the largest. If the underlying range supports put(), then Heap also supports put() to insert into the heap.

Heap as a container would offer similar primitives but in addition would "own" its data (would call destructors upon destruction, and would support value copying).

What do you think? Should I make Heap a container or a range?


Andrei
January 30, 2009

Andrei Alexandrescu wrote:
> A "computer science heap" is a structure that offers fast access to the largest element and fast extraction of it (which in turn provides access to the next largest element etc.).
> 
> I'm just done working on the heap in std.algorithm. Now, it turns out that heap supports both a meaningful definition as a full-fledged container, and a beautiful definition as a range.
> 
> If Heap is a range, you initiate it with another range, which Heap
> organizes in the heap manner. Then, successive calls to next() nicely
> extract elements starting from the largest. If the underlying range
> supports put(), then Heap also supports put() to insert into the heap.
> 
> Heap as a container would offer similar primitives but in addition would "own" its data (would call destructors upon destruction, and would support value copying).
> 
> What do you think? Should I make Heap a container or a range?
> 
> 
> Andrei

I suppose it comes down to whether or not the typical case is to either have a heap or heap-view of another container.  I'd suspect the first, to be honest.

You could always just have Heap and HeapView.  :)

  -- Daniel
January 30, 2009
On Fri, Jan 30, 2009 at 11:49 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> A "computer science heap" is a structure that offers fast access to the largest element and fast extraction of it (which in turn provides access to the next largest element etc.).

In response to your previous question of how to distinguish from a memory heap, you can use the specific name for the kind of heap it is, like BinaryHeap, Binomial Heap, Fibbonocci Heap, etc.


> I'm just done working on the heap in std.algorithm. Now, it turns out that heap supports both a meaningful definition as a full-fledged container, and a beautiful definition as a range.
>
> If Heap is a range, you initiate it with another range, which Heap organizes
> in the heap manner. Then, successive calls to next() nicely extract elements
> starting from the largest. If the underlying range supports put(), then Heap
> also supports put() to insert into the heap.
>
> Heap as a container would offer similar primitives but in addition would "own" its data (would call destructors upon destruction, and would support value copying).
>
> What do you think? Should I make Heap a container or a range?

Both sound useful depending on circumstances.  One provides the all-in-one convenient solution, the other is more of a "non-invasive heap".

If you emphasize the non-invasive version, then creating the all-in-one version out of that should be pretty easy.  But you can't take an all-in-one and turn it non-invasive so easily.

--bb
January 30, 2009
Bill Baxter wrote:
> On Fri, Jan 30, 2009 at 11:49 AM, Andrei Alexandrescu
> <SeeWebsiteForEmail@erdani.org> wrote:
>> A "computer science heap" is a structure that offers fast access to the
>> largest element and fast extraction of it (which in turn provides access to
>> the next largest element etc.).
> 
> In response to your previous question of how to distinguish from a
> memory heap, you can use the specific name for the kind of heap it is,
> like BinaryHeap, Binomial Heap, Fibbonocci Heap, etc.

BinaryHeap it is. Thanks!

>> I'm just done working on the heap in std.algorithm. Now, it turns out that
>> heap supports both a meaningful definition as a full-fledged container, and
>> a beautiful definition as a range.
>>
>> If Heap is a range, you initiate it with another range, which Heap organizes
>> in the heap manner. Then, successive calls to next() nicely extract elements
>> starting from the largest. If the underlying range supports put(), then Heap
>> also supports put() to insert into the heap.
>>
>> Heap as a container would offer similar primitives but in addition would
>> "own" its data (would call destructors upon destruction, and would support
>> value copying).
>>
>> What do you think? Should I make Heap a container or a range?
> 
> Both sound useful depending on circumstances.  One provides the
> all-in-one convenient solution, the other is more of a "non-invasive
> heap".
> 
> If you emphasize the non-invasive version, then creating the
> all-in-one version out of that should be pretty easy.  But you can't
> take an all-in-one and turn it non-invasive so easily.

Ah, never mind all that. I realized that I can't have a heap range. This is because heaps must mutate the underlying range in-place and any copy will mess the heap up. Here's the example that clarify it for me:

        int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
        auto h = Heap!(int[])(a);
        assert(equal(take(5, h) == [ 8, 9, 10, 14, 16 ]);

At this point the mutations done by take messed up h already!!


Andrei
January 30, 2009
Hello Andrei,

> What do you think? Should I make Heap a container or a range?
> 
> Andrei
> 

what would be the problem of making it (optionaly) both? 


January 30, 2009
On Fri, Jan 30, 2009 at 12:14 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> Bill Baxter wrote:
>>
>> On Fri, Jan 30, 2009 at 11:49 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
>>>
>>> A "computer science heap" is a structure that offers fast access to the
>>> largest element and fast extraction of it (which in turn provides access
>>> to
>>> the next largest element etc.).
>>
>> In response to your previous question of how to distinguish from a memory heap, you can use the specific name for the kind of heap it is, like BinaryHeap, Binomial Heap, Fibbonocci Heap, etc.
>
> BinaryHeap it is. Thanks!
>
>>> I'm just done working on the heap in std.algorithm. Now, it turns out
>>> that
>>> heap supports both a meaningful definition as a full-fledged container,
>>> and
>>> a beautiful definition as a range.
>>>
>>> If Heap is a range, you initiate it with another range, which Heap
>>> organizes
>>> in the heap manner. Then, successive calls to next() nicely extract
>>> elements
>>> starting from the largest. If the underlying range supports put(), then
>>> Heap
>>> also supports put() to insert into the heap.
>>>
>>> Heap as a container would offer similar primitives but in addition would
>>> "own" its data (would call destructors upon destruction, and would
>>> support
>>> value copying).
>>>
>>> What do you think? Should I make Heap a container or a range?
>>
>> Both sound useful depending on circumstances.  One provides the all-in-one convenient solution, the other is more of a "non-invasive heap".
>>
>> If you emphasize the non-invasive version, then creating the all-in-one version out of that should be pretty easy.  But you can't take an all-in-one and turn it non-invasive so easily.
>
> Ah, never mind all that. I realized that I can't have a heap range. This is because heaps must mutate the underlying range in-place and any copy will mess the heap up. Here's the example that clarify it for me:
>
>        int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
>        auto h = Heap!(int[])(a);
>        assert(equal(take(5, h) == [ 8, 9, 10, 14, 16 ]);
>
> At this point the mutations done by take messed up h already!!

Messed 'h' up or messed 'a' up?

Anyway, in that case it would be nice if you can easily run the heap indirectly on an index or pointer buffer.

Will something like this work?
HeavyElement[] arrayOfHeavies;
auto h = Heap!(int[], (int i, int j){return
arrayOfHeavies[i]<arrayOfHeavies[j];} )( 0..arrayOfHeavies.length )

Now   arrayOfHeavies[h.pop()] should give you the smallest element of the array of heavies, without ever having to copy/swap anything but ints.

--bb
January 30, 2009
Andrei Alexandrescu Wrote:

> Bill Baxter wrote:
> > On Fri, Jan 30, 2009 at 11:49 AM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> >> A "computer science heap" is a structure that offers fast access to the largest element and fast extraction of it (which in turn provides access to the next largest element etc.).
> > 
> > In response to your previous question of how to distinguish from a memory heap, you can use the specific name for the kind of heap it is, like BinaryHeap, Binomial Heap, Fibbonocci Heap, etc.
> 
> BinaryHeap it is. Thanks!
> 
> >> I'm just done working on the heap in std.algorithm. Now, it turns out that heap supports both a meaningful definition as a full-fledged container, and a beautiful definition as a range.
> >>
> >> If Heap is a range, you initiate it with another range, which Heap organizes
> >> in the heap manner. Then, successive calls to next() nicely extract elements
> >> starting from the largest. If the underlying range supports put(), then Heap
> >> also supports put() to insert into the heap.
> >>
> >> Heap as a container would offer similar primitives but in addition would "own" its data (would call destructors upon destruction, and would support value copying).
> >>
> >> What do you think? Should I make Heap a container or a range?
> > 
> > Both sound useful depending on circumstances.  One provides the all-in-one convenient solution, the other is more of a "non-invasive heap".
> > 
> > If you emphasize the non-invasive version, then creating the all-in-one version out of that should be pretty easy.  But you can't take an all-in-one and turn it non-invasive so easily.
> 
> Ah, never mind all that. I realized that I can't have a heap range. This is because heaps must mutate the underlying range in-place and any copy will mess the heap up. Here's the example that clarify it for me:
> 
>          int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
>          auto h = Heap!(int[])(a);
>          assert(equal(take(5, h) == [ 8, 9, 10, 14, 16 ]);
> 
> At this point the mutations done by take messed up h already!!

I would have expected index take(h,5)[0] to be 16...

I still have yet to come to terms with passing ranges by value. I would expect take to modify my range. I naturally expect heaps to be destructive as elements are taken out. I also expect ranges to shrink. I don't see any issue...
January 30, 2009
Bill Baxter wrote:
> On Fri, Jan 30, 2009 at 12:14 PM, Andrei Alexandrescu
>> Ah, never mind all that. I realized that I can't have a heap range. This is
>> because heaps must mutate the underlying range in-place and any copy will
>> mess the heap up. Here's the example that clarify it for me:
>>
>>        int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
>>        auto h = Heap!(int[])(a);
>>        assert(equal(take(5, h) == [ 8, 9, 10, 14, 16 ]);
>>
>> At this point the mutations done by take messed up h already!!
> 
> Messed 'h' up or messed 'a' up?

'a' is messed up (mutated) by definition. The problem is that after h was copied to do take's deed, it got messed up (i.e., doesn't respect the heap property anymore).

> Anyway, in that case it would be nice if you can easily run the heap
> indirectly on an index or pointer buffer.
> 
> Will something like this work?
> HeavyElement[] arrayOfHeavies;
> auto h = Heap!(int[], (int i, int j){return
> arrayOfHeavies[i]<arrayOfHeavies[j];} )( 0..arrayOfHeavies.length )
> 
> Now   arrayOfHeavies[h.pop()] should give you the smallest element of
> the array of heavies, without ever having to copy/swap anything but
> ints.

Yah, that should work. You just need to initially fill the heap with the numbers 0 to arrayOfHeavies.length. I presume that's what you meant with the illegal slicing notation :o).


Andrei
January 30, 2009
> I still have yet to come to terms with passing ranges by value. I
> would expect take to modify my range. I naturally expect heaps to be
> destructive as elements are taken out. I also expect ranges to
> shrink. I don't see any issue...

Both ways have advantages and disadvantages. My early experiments involved passing by reference and it was an absolute mess: I'd forget a "ref" here and there with weird results, or I'd forget to save a copy of my range and I'd find is shrunk like an dehydrated fig in no time. One advantage of pass by value is that code is shorter and nicer - no need for a lot of temporaries.

Andrei
January 30, 2009
On Fri, Jan 30, 2009 at 1:17 PM, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> wrote:
> Bill Baxter wrote:
>>
>> On Fri, Jan 30, 2009 at 12:14 PM, Andrei Alexandrescu
>>>
>>> Ah, never mind all that. I realized that I can't have a heap range. This
>>> is
>>> because heaps must mutate the underlying range in-place and any copy will
>>> mess the heap up. Here's the example that clarify it for me:
>>>
>>>       int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
>>>       auto h = Heap!(int[])(a);
>>>       assert(equal(take(5, h) == [ 8, 9, 10, 14, 16 ]);
>>>
>>> At this point the mutations done by take messed up h already!!
>>
>> Messed 'h' up or messed 'a' up?
>
> 'a' is messed up (mutated) by definition. The problem is that after h was
> copied to do take's deed, it got messed up (i.e., doesn't respect the heap
> property anymore).
>
>> Anyway, in that case it would be nice if you can easily run the heap indirectly on an index or pointer buffer.
>>
>> Will something like this work?
>> HeavyElement[] arrayOfHeavies;
>> auto h = Heap!(int[], (int i, int j){return
>> arrayOfHeavies[i]<arrayOfHeavies[j];} )( 0..arrayOfHeavies.length )
>>
>> Now   arrayOfHeavies[h.pop()] should give you the smallest element of the array of heavies, without ever having to copy/swap anything but ints.
>
> Yah, that should work. You just need to initially fill the heap with the numbers 0 to arrayOfHeavies.length. I presume that's what you meant with the illegal slicing notation :o).

Ok. great.  I thought that the slicing notation to make a sequence worked everywhere now in D2.  I guess it's only inside a foreach.

--bb
« First   ‹ Prev
1 2 3