views:

198

answers:

4

What is the name for the sort used in this answer? I Googled for "perfect insertion sort" but didn't find anything. Here is the code from that answer:

#this is O(n) instead of O(n log n) or worse
sub perfect_insert_sort {
    my $h = shift;
    my @k;
    for my $k (keys %$h) {
        $k[$h->{$k}{order}] = $k;
    }
    return @k;
}
A: 

I think it's nothing but an insertion sort.

No, an [`insertion sort`](http://en.wikipedia.org/wiki/Insertion_sort) is different (see the link and the one in my answer). I was just too lazy to go look up the right name, so I threw perfect on the start and called it done.
Chas. Owens
+7  A: 

I think I probably should have named that perfect_bucket_sort instead of perfect_insertion_sort.

Chas. Owens
It still doesn't perform any sorting. See [my updated answer](http://stackoverflow.com/questions/3658761/is-there-a-name-for-this-sort/3661108#3661108) for why. Sorting implies a determination of order. This is not determining order, merely reconstituting it.
Robert P
@Robert P `perl -MList::Util=shuffle -le '$a[$_] = $_ for shuffle 0 .. 9; print for @a'` is just as much a sort as `perl -MList::Util=shuffle -le 'print for sort { $a <=> $b } shuffle 0 .. 9'` The first is just significantly faster (because we know stuff about the value we are sorting on and can cheat). Go back and reread that wikipedia page.
Chas. Owens
+3  A: 

This isn't insertion sort, in fact it's not even a comparison sort because the theoretical lowest bound for those is O(nlogn).

So it's probably bucket sort; also notice there are no comparisons made :)

Swizec Teller
A: 

It's not really a sort at all. it is, in fact, primarily a map or a transformation. This is an example of the data structure they have:

my $hash = {
   foo => { order => 3 },
   bar => { order => 20 },
   baz => { order => 66 }, 
};

It's simply a translation of 'order' to elements in an array. For example, if you pass in this $hash to perfect_insert_sort, it will return a 67 element array, with three items (one at index 3, one at 20, and one at 66) and the rest being undef, and entirely in an unsorted order.

Nothing about that function does any sorting of any kind. If there is any sorting going on in that other answer, it's happening before the function is called.

@downvoter:

And looking at the other answer, the sorting happens at insertion time. THAT component might be considered a sort. This subroutine, however, does not create that order - it merely reconstitutes it.

Take a look at the classical definition for a sort:

  1. The output is in nondecreasing order (each element is no smaller than the previous element according to the desired total order)
  2. The output is a permutation, or reordering, of the input.

Part 2 is certainly being satisfied: there is a transformation of the hash structure to a list going on. However, part 1 is not satisfied. There is no determining of order going on. The order has been predetermined during insertion. If this were a 'sort', then the following would also be a sort:

my @data = ... ;
my $index = -1;
my %stored = map { ++$index; $_ => { order => $index } } @data;
my @remade_data;
@remade_data[(map { $stored{$_}{order} } keys %stored)] = keys %stored;

As you can see, there is no sorting going on in that chunk of code, merely transformation.

Robert P
Then what do you call the radix sort, counting sort, and bucket sort? They are all named sorts on that page (and the algorithm is either a bucket sort or a counting sort depending on how you look at). You are indeed sorting the keys **by when they were inserted into the hash**, not by their values. If you go read the [code in question](http://stackoverflow.com/questions/3638690/iterating-hash-based-on-the-insertion-order/3638696#3638696) you will see that the sort is on insert order, not value of the keys. In terms of Perl 5's sort it would be `sort { $h{$a}{order} <=> $h{$b}{order} }`.
Chas. Owens