# these lines replace "P=$1" line:
local first=$1
eval local last=\${$#}
eval local mid=\${$((($#+1)/2))}
if [ $first -le $mid ] ; then
if [ $mid -le $last ] ; then
P=$mid
elif [ $first -le $last ] ; then
P=$last
else
P=$first
fi
else
if [ $first -le $last ] ; then
P=$first
elif [ $mid -le $last ] ; then
P=$last
else
P=$mid
fi
fi
That little enhancement blows up the LOC quite a bit. :)
The time complexity looks very bad (assuming I can read shell, which I am not sure about).
First it appears it has the classic bug of passing items equal to the partition to sub-sorts (G in this case). This guarantees N recurses (and at least c N^2 operations) when trying to sort an array that is all duplicates of a single value. Also the list concatenations ( L="$L $i" and G="$G $i") which often make mere list assembly take c N^2 time (pretty much forced by the string representations). So this could be a c N^3 worst-case sorting algorithm (possibly worse than bubble sort).
I meant that the canonical quicksort algorithm which Hoare came up uses in-place partitioning. Probably you can still call "quicksort" to these nice snippets (be it in Prolog, Erlang or Haskell), but mentioning the fact about the deviation from the canonical implementation could be useful for readers.
I what must be a lapse of sanity, I wrote mergesort. It is quite a bit more than 3 - err, 14 - lines, but it does include an option to see view the array nesting.
It uses slightly better array management... and then throws out any gains by rebuilding a new array every time an element is shift off the front.