*! 1.0.0 Aug97 Jeroen Weesie/ICS STB-45 ip14.1 * non-recursive quicksort (Wirth 1976: 80, with modification p 82) * qsort list , options (items in list caanot contain , sorry) program define qsort version 5.0 if "`*'" == "" { global S_1 exit } * parse command line so that input-to-be-sorted is still stored * in macros 1, 2, 3, ... parse "`*'", p(" ,") local n 1 while "``n''" ~= "" & "``n''" ~= "," { local n = `n'+1 } local n = `n'-1 * store the rest in opt, and clear superfluous macros local lopt = `n'+1 while "``lopt''" ~= "" { local opt "`opt' ``lopt''" local `lopt' local lopt = `lopt'+1 } if "`opt'" ~= "" { local options "Ascend Descend ALpha DIsplay" parse "`opt'" } * store input-list for display with output if "`display'" ~= "" { local list "`*'" } * check that input is numeric if "`alpha'" == "" { local i 1 while `i' <= `n' { confirm number ``i'' local i =`i'+1 } } /* if "`file'" ~= "" { quietly { preserve tempvar x drop _all set obs `n' gen `x' = . if "`descend'" ~= "" & "`ascend'" == "" { local sgn "-" } local i 1 while `i' <= `n' { replace `x' = `sgn' ``i'' in `i' local i = `i'+1 } sort `x' local i 1 while `i' <= `n' { local `i' = `sgn' `x'[`i'] local i = `i'+1 } } } */ * sorting order if "`descend'" ~= "" & "`ascend'" == "" { local direct ">" } else local direct "<" * non-recursive quicksort local s 1 local stl_1 1 /* stack[s].l == stl_s */ local str_1 `n' /* stack[s].r == str_s */ while `s' > 0 { /* take top request from stack */ local l `stl_`s'' local r `str_`s'' local s = `s'-1 while `l' < `r' { /* split list[l] ... list[r] */ local i `l' local j `r' local ix = int((`l'+`r')/2) local x ``ix'' while `i' <= `j' { if "`alpha'" == "" { while ``i'' `direct' `x' { local i = `i'+1 } while `x' `direct' ``j'' { local j = `j'-1 } } else { while "``i''" `direct' "`x'" { local i = `i'+1 } while "`x'" `direct' "``j''" { local j = `j'-1 } } if `i' <= `j' { /* swap elements i and j */ local w ``i'' local `i' ``j'' local `j' `w' local i = `i'+1 local j = `j'-1 } } * stack request to sort either left or right partition if `j'-`l' < `r'-`i' { if `i' < `r' { /* sort right partition */ local s = `s'+1 local stl_`s' `i' local str_`s' `r' } local r `j' } else { if `l' < `j' { /* sort left partition */ local s = `s'+1 local stl_`s' `l' local str_`s' `j' } local l `i' } } /* while l < r */ } * re-assemble 1,2,3... into S_1 global S_1 "`*'" if "`display'" ~= "" { di in gr "`list'" in ye " -> " in gr "$S_1" } end exit In a first version of qsort I parsed the command line on a comma to split input in the list-to-be-sorted and the options. I found out that this does not work with lists that exceed 517 characters --- this turns out to be the maximal length of tokens in parsing. (shit...)