Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Quicksort (of a stack)

by robin (Chaplain)
on Mar 26, 2002 at 08:33 UTC ( [id://154349]=note: print w/replies, xml ) Need Help??


in reply to Algorithm Pop Quiz: Sorting

Here's a basic quicksort implementation. Because we don't have random access to the stack, I've used the top element as the pivot. That has the unfortunate effect that we get worst-case (quadratic) behaviour if the input list is already sorted! Bubblesort would actually be better in that case. For a random input list, the asymptotic behaviour should be O(n log n), on the assumption that rotate_up takes constant time.

I think it'll translate to fewer than 50 instructions of assembler, but I don't have kids or a car :-)

sub debug ($;@) { # Uncomment the next line to see a partial execution trace # print @_; } my @stack = @ARGV; # Initialise the stack with test value +s push @stack, scalar(@stack); # Push the length quicksort(); # call the sort routine print "Result: @stack\n"; # and print the result sub quicksort { local ($n) = pop(@stack); push @stack, $n; push @stack, 0; sort_and_tuck(); push @stack, $n; } sub sort_and_tuck { local ($w) = pop(@stack); # where to put result local ($c) = pop(@stack); # number of items debug " \$w=$w; \$c=$c; \@stack=@stack\n"; if ($c == 1) { rotate_up($w+1); } elsif ($c > 1) { local ($p) = pop(@stack); # pivot $c--; local ($n) = $c; local ($i) = $c; debug "\t< \$p=$p; \$n=$n"; while ($i--) { local ($e) = pop(@stack); # examine top element push @stack, $e; debug "\t\t\$e=$e (@stack)\n"; if ($p gt $e) { rotate_up($c); -- $n; } else { rotate_up($n); } } debug "\t> \$n=$n\n"; # Now we've partitioned the list. The top $n elements are gt $ +p, # and the next ($c-$n) are le $p. Sort the partitions. local($r) = $c-$n; push @stack, $n; push @stack, $w+$r; sort_and_tuck(); push @stack, $r; push @stack, $w; sort_and_tuck(); push @stack, $p; # Reinsert the pivot rotate_up(1+$w+$r); debug " Return: @stack\n" } } # Should be called put_away(), but I'm not allowed to modify it ;-) sub rotate_up { local($a,$b); $a=$_[0]; $a--; return if $a<1; $b=pop @stack; splice(@stack, -$a, 0, $b); }

Replies are listed 'Best First'.
Re: Quicksort (of a stack)
by clintp (Curate) on Mar 26, 2002 at 12:58 UTC
    Excellent. If you'll notice I *did* post a function (in PASM) that does a peek into the stack. The $2 question is, does the overhead of that function destroy the benefits of a quicksort? (I'll bet it does.) This is kinda cool though.
      Yeah I agree. I don't think it would be worth it.

      The quicksort should still be quicker than bubblesort most of the time - substantially quicker if there are a lot of elements to sort. If you do get this implemented in parrotcode, I'd be interested in seeing any benchmarks etc.

      It's an interesting curiosity that it's possible to do a sensible quicksort at all. I briefly considered using mergesort, but I don't think it can be done at all efficiently because there's only one stack.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://154349]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (None)
    As of 2024-04-25 00:53 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found