note
Adam
That doesn't make much sense [Tye]. Qsort is, afterall, an implementation of Quicksort. Quicksort is a pretty smart algorithm for sorting an array by loading the whole thing into memory. (In fact, it has also been proven to be the most efficient algorithm for sorting a large array. You can't do better then bigO(n log n))<p>
<i>We break from this post to give a brief description of quicksort for those who don't know.</i><br>
Quicksort is a recursive algorithm that picks a pivot element out of the array and then compares all the other elements to it. This results in two arrays and the pivot, where one array is all items "greater then" the pivot and the other is all items "less then" the pivot. Quicksort is then used to sort these two arrays. Since its done recursivly, it ends up with an array of pivot points in order. The code might look something like this:
<code>
sub Qsort # WRONG! See update below!
{
my $pivot = shift; # picking the pivot is usually more
# involved. Afterall, you don't want
# an extreme, you want both arrays to
# be roughly the same size.
return $pivot unless @_;
my( @lt, @gt );
push( $_ gt $pivot ? @gt : @lt ) for @_;
return( Qsort( @lt ), $pivot, Qsort( @gt ) );
}
</code>
(Disclaimer: I didn't test that and I havn't looked any of this up, so I could be completly wrong and that code might not work)<br><i>We now return to the post already in progress</i><p>
So you see, the amount of time <tt>@a = sort {(-1,1)[rand 2]} @a</tt> will take is finite and well defined, regardless of the function used to determine which side of the pivot to place each element. So the only reason it would dumb core would be that it ran out of memory, but it should never become hung (unless, as I said, it ran out of memory... those sneaky recursive algorithms). The only thing that varies in a quicksort is how well the pivot is chosen. If you pick an extreme (where everything ends up on one side of the pivot) then Qsort will take much longer then if you pick the middle where everything is balanced. So the point of all this is that I doubt the implementation has gotten better, but rather the hardware (128 MB ram sure beats 2 or 4 MB).
<p><b>Update:</b><br>
So I did a little research on Quicksort and realized that it usually operates on the array in place, which mine clearly doesn't. And that it does even less work then mine did. How about:
<code>
sub Qsort
{
my( $arrayRef, $lowIndex, $highIndex ) = @_;
return undef if $highIndex le $lowIndex;
my $pivotIndex = partition( $arrayRef, $lowIndex, $highIndex );
Qsort( $arrayRef, $lowIndex, $pivotIndex - 1 );
Qsort( $arrayRef, $pivotIndex + 1, $highIndex );
}
# And then, of course, I need to provide &partition
sub partition
{
my( $arrayRef, $lowIndex, $highIndex ) = @_;
my $pivot = $highIndex + $lowIndex >> 1;
my $pivotElement = $$arrayRef[$pivot];
while( $highIndex > $lowIndex )
{
++$lowIndex while $$arrayRef[$lowIndex] <= $pivotElement and $_[2] > $lowIndex;
--$highIndex while $pivotElement <= $$arrayRef[$highIndex] and $highIndex > $_[1];
Swap( $arrayRef, $lowIndex, $highIndex ) if $highIndex > $lowIndex;
}
if( $highIndex > $pivot )
{
Swap( $arrayRef, $pivotIndex, $highIndex );
$pivot = $highIndex;
}
elsif( $pivot > $lowIndex )
{
Swap( $arrayRef, $pivotIndex, $lowIndex );
$pivot = $lowIndex;
}
return $pivot;
}
sub Swap { ${$_[0]}->[$_[1],$_[2]] = ${$_[0]}->[$_[1],$_[2]] }
# Warning, untested code...
</code>
For more about sorting, check out these great documents I found: <A href="http://www.sysarch.com/perl/sort_paper.html">Here</a> and <A href="http://www.compapp.dcu.ie/~abolger/gdf/Quicksort.html">here</a>. <br>
Not to forget [Buy Stuff|Mastering Algorithms with Perl] from O'Reilly, which has a whole chapter devoted to sorting algorithms.
<p>
BTW: After at least an hour of working on this post I have realized that a true quicksort would, in fact, go crazy given <tt>{ (-1,1)[rand 2] }</tt> and I am now somewhat mystified as to why it converges at all. I think its time to go eat something and I will return to this later.
<p>
Update:<br>
So I slept on it, and I am now re-convinced that Qsort will be finite regardless of the random nature of its partition. So I go back to the original point of this post, [Tye], that Qsort should only fail if it runs out of memory for all those recursive calls, and that it should end in a finite amount of time not to exceed some constant times N squared. (N being the number of elements to be sorted.)<p>
My apologies to anyone that I have confused with this post. Maybe it will inspire you to learn more about <tt>sort</tt>.
31461
31521