%Contents: Sorting via TeX (heap and quick) %Submission CTAN % Introduced at TUG 93. %Version: 1.0 December 1993. %Purpose: Sorting within TeX. %Example of use (after \input sort.tex %the auxiliaries % \input heap.tex resp. quick.tex %the macros) %Documentation: Proceedings TUG 93, Aston, TUGboat 14.3, (abridged) % and MAPS 93.1 (complete) %C.G. van der Laan, Hunzeweg 57, 9893PB, Garnwerd. Holland. 05941-1525. % cgl@risc1.rug.nl %For TeX-ing this contribution use ltugproc.sty; the macros can be used %with AllTeX. %This file contains % - History of changes % - Auxiliaries (sort.tex) % - heap.tex % - quick.tex % - Example heap sort % - quick sort % %%%%%%%%%% History of changes %%%%%%%%%% %History of change files %Jan 1994: Submission CTAN. % %Next follows the two appendices as supplied in TUGboat 14, 3 with the macros %included, so that it can be processed by ltugproc.sty \documentstyle{ltugproc} \title{Sorting macros} \author{Kees van der Laan} \address{Hunzeweg 57, 9893 PB, Garnwerd, The Netherlands} \netaddress[\network{Internet}]{cgl@risc1.rug.nl} \begin{abstract} The macros as submitted for CTAN. They are embedded in an article which consists of the appendices heap sort and quick sort. The latter show the low level use of the (worker) macros. For high level use see the article in TUGBoat 14, 3, (TUG 93) or the complete---Sorting in BLUe---as released in MAPS 93.1. \end{abstract} \maketitle \let\ftn\footnote \begin{document} \noindent Contents of file\\ - sort.tex (auxiliaries)\\ - heap.sort (specific for heap sort)\\ - quick.sort (specific for quick sort)\\ - the two appendices. \vfill\eject % %%%%%%%%%% Auxiliaries sort.tex %%%%%%%%%% %Sort tex macros%sort.tex Jan 93 %Shorthands \let\ag=\aftergroup \let\ea=\expandafter\let\nx=\noexpand %Counters \newcount\n\newcount\k\newcount\kk\n=0 \newcount\kzero\kzero0 %Bias value \newcount\pk\newcount\pkone%Used in sortcs \newcount\frst%First value of range \newcount\lst %Last value of range \newcount\slst%Successor \lst \newcount\dif %Difference \lst-\frst \newcount\nw %Number of words \newcount\nc %Number of characters/comp \newcount\numex %Number of exchanges \newcount\rndval%Random number \newcount\rndnum%Seed random generator \newcount\rndtmp%Temporary value \newcount\status%Status comparison %Newif-s \newif\ifcontinue%controls loops \newif\iffound%locating accent cs \newif\ifproof\prooftrue % %Storing: from copy \def\seq#1\qes{\k0 \fifow#1 \wofif{} } %Auxiliaries: FIFO \def\fifow#1 {\ifx\wofif#1\n\k\wofif\fi \processw{#1}\fifow} \def\wofif#1\fifow{\fi} \def\processw#1{\advance\k1 \ea \gdef\csname\the\k\endcsname{#1}} % %Storing: from file \newread\rec \def\storefrom#1{%#1 is file name \openin\rec=#1 \k\kzero \continuetrue \loop\ifeof\rec\continuefalse\fi \ifcontinue\advance\k1{}\read\rec to\xyz \ea\let\csname\the\k\endcsname=\xyz \repeat\advance\k-1\n\k\closein\rec} % %Storing: random numbers \def\storerandomn#1{%#1 number of numbers \n#1\k0 \loop\ifnum\k<\n\advance\k1 \rnd\ea \xdef\csname\the\k\endcsname{\the\rndval} \repeat} % %With, due to Reid, 1987 \def\rnd{\global\multiply\rndnum371{}% \global\advance\rndnum1{}% \ifnum\rndnum>99999 \rndtmp\rndnum \divide\rndtmp100000 \multiply\rndtmp100000 \global\advance\rndnum-\rndtmp \fi\global\rndval\rndnum \global\divide\rndval1000 } % %Storing: random words \def\storerandomw#1{%#1 number of words \n#1\nw\n\def\defarr{\ea\gdef \csname\the\nw\endcsname} {\loop\ifnum0<\nw{\ag\defarr\ag{% \randomword}}\advance\nw-1 \repeat}}%end s-r-w. % \def\randomword{\rnd \nc\rndval \divide\nc15 \advance\nc2 \loop\ifnum0<\nc\randomchar \advance\nc-1 \repeat}%end r-word % %Random character is modified \def\randomchar{\rnd \multiply\rndval29 \divide\rndval100 \ifnum26=\rndval\rndval0 \fi \ifnum26<\rndval\rndval4 \fi %Mod cgl: I \ag-ed the letter \ea\ag\ifcase\rndval a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or n\or o\or p\or q\or r\or s\or t\or u\or v\or w\or x\or y\or z\fi}%end r-char % %Typeset %Parameters: Separators \def\sepn{, }%Number separator \def\sepw{ } %Word separator \let\sep\sepw % \def\prc#1{\init{#1}\def\prc##1{% \ifnum\lst=##1{}\else\ifnum\slst=##1{}% \lst\slst\advance\slst1{}\else \prtfl\sepn\init{##1}\fi\fi}} % \def\init#1{\frst=#1\lst=#1\slst=#1{}% \advance\slst1{}} % %Print range: \frst-\lst (or \lst). \def\prtfl{\the\frst\ifnum\frst<\lst \advance\frst1{}\ifnum\frst=\lst\sepn \else\nobreak--\nobreak\fi\the\lst\fi} % %Printing sequences \def\prts{{\k\kzero%print \1,...\n \def\sep{\let\sep=\sepw}% \loop\ifnum\k<\n\advance\k1 \sep\csname\the\k\endcsname \repeat}}%end \prts % \let\prtw=\prts % \def\prtn{{\k\kzero%Print number sequence \loop\ifnum\k<\n\advance\k1 \ea\prc\csname\the\k\endcsname \repeat\prtfl}}%end \prtn % \def\typind#1{%#1 a def \ea\splittot#1.% \ifcase\digit\word\or {\tt\word}\or {\tt\char92\word}\or $\langle\hbox{\word}\rangle$\fi{} \pagenrs} % \def\splittot#1 !#2 #3.{\def\word{#1}% \chardef\digit=#2{}\def\pagenrs{#3}} % \def\prtind{{\def\\{\hfil\break}\k\kzero \def\sep{\let\sep\sepw}% \loop\ifnum\k<\n\advance\k1 \sep\ea\typind\csname\the\k\endcsname \repeat}} % %Sorting in O(nlog n) %Numbers \def\sortn{\let\cmp\cmpn\sort\prtn} % %ASCII words \def\sortaw{\let\cmp\cmpaw\sort\prtw} % %Words (with accents) \def\sortw{\let\cmp\cmpw{\accdef\sort}\prtw} % \def\sort{\heapsort} % %Paramaters: ij and accent string \def\accstr{\`\'\"\^\c} % \def\accdef{\def\i{i}\def\j{j}% \def\'##1{##1a}\def\`##1{##1g}% \def\"##1{##1t}\def\^##1{##1h}% \def\c##1{##1c}} % \def\ij{ij} % %Sorting parameters: exchange macro \def\xch#1#2{%#1, #2 counter variables \ea\let\ea\auxone\csname\the#1\endcsname \ea\let\ea\auxtwo\csname\the#2\endcsname \ea\global\ea\let\csname\the#2\endcsname \auxone \ea\global\ea\let\csname\the#1\endcsname \auxtwo} % %Sorting parameters: number comparison \def\cmpn#1#2{%#1, #2 are def-s %Result: \status= 0, 1, 2, if % \val{#1} =, >, < \val{#2} \ifnum#1=#2\global\status0 \else \ifnum#1>#2\global\status1 \else \global\status2 \fi\fi} % %Parameters: comparison of words \def\cmpw#1#2{%#1, #2 are def-s %Result: \status= 0, 1, 2, if % \val{#1} =, >, < \val{#2} \let\nxt\nxtw\cmpc#1#2} % \def\cmpaw#1#2{%#1, #2 are defs with as %replacement text the words. %Result: \status= 0, 1, 2, if % \val{#1} =, >, < \val{#2} \let\nxt\nxtaw\cmpc#1#2} % \def\cmpc#1#2{%#1, #2 are def-s %Result: \status= 0, 1, 2, if % \val{#1} =, >, < \val{#2} \ifproof\global\advance\nc1 \let\aa#1\let\bb#2\fi \global\status0 \continuetrue {\loop\ifx\empty#1\continuefalse\fi \ifx\empty#2\continuefalse\fi \ifcontinue\nxt#1\nxtt\nxt#2\nxtu \lge\nxtt\nxtu \repeat}\ifnum0=\status \ifx\empty#1\ifx\empty#2\else \global\status2 \fi \else\ifx\empty#2\global\status1 \fi \fi\fi \ifproof\immediate\write16{\aa \ifnum0=\status=\else \ifnum1=\status>\else <\fi\fi\bb.} \fi%end ifproof } % \def\lge#1#2{%#1 and #2 letter values %Result: \status= 0, 1, 2, if % #1 =, >, < #2. %and \continuefalse if #1=/#2. \ifnum#1=#2{}\else\continuefalse \ifnum#1<#2\global\status2 \else \global\status1 \fi \fi} % \def\nxtw#1#2{\def\pop##1##2\pop{% \gdef#1{##2}\def\head{##1}}%head and tail \ea\pop#1\pop%split in head and tail \ea\loc\head\accstr%\head is an accent cs? \iffound\let\acs\head \ea\pop#1\pop%next head and tail \ea\let\ea#2\csname ot\acs\head\endcsname \else\ea\let\ea#2\csname ot\head\endcsname \fi} % \def\loc#1#2{\def\locate##1#1##2\end {\ifx\empty##2\empty\foundfalse \else\foundtrue\fi}\ea\locate#2.#1\end} % %Parameters: for ASCII words \def\nxtaw#1#2{%Result: value of first %letter of string supplied in #1 is delivered %in #2. (To be used as a number (\chardef)). %#1, #2 are control sequences. \def\pop##1##2\pop{\gdef#1{##2}% \chardef#2=`##1{}}\ea\pop#1\pop} % \def\cmpir#1#2{%#1, #2 defs %Result: \status= 0, 1, 2 if % \val{#1} =, >, < \val{#2} \ea\ea\ea\decom\ea#1\ea;#2.} % \def\decom#1 !#2 #3;#4 !#5 #6.{% \def\one{#1}\def\four{#4}\cmpaw\one\four \ifnum0=\status%Compare secondary keys \ifnum#2<#5{}\global\status2{}\else \ifnum#2>#5{}\global\status1{}\else %Compare tertiary keys \ifnum#3<#6{}\global\status2{}\else \ifnum#3>#6{}\global\status1{}\fi \fi \fi \fi \fi} % \def\red{%Reduction of \1,...,\n \k0\kk0\let\refer\empty \loop\ifnum\k<\n\advance\k1 \ea\let\ea\record\csname\the\k\endcsname \ea\splitwn\record.% \ifx\refer\word%extend with number \ea\xdef\csname\the\kk\endcsname{% \csname\the\kk\endcsname, \num}% \else%write record to \kk \advance\kk1\let\refer\word\ea\global \ea\let\csname\the\kk\endcsname\record \fi \repeat\n=\kk} % \def\redrng{%Reduction of \1,...,\n, with %range representation of page numbers {\k1\kk0 \ea\let\ea\record\csname\the\k\endcsname \ea\splitwn\record.\let\refer\word \let\nrs\empty\prcrng\num \loop\ifnum\k<\n\advance\k1 \ea\let\ea\record\csname\the\k\endcsname \ea\splitwn\record.% \ifx\refer\word%extend \nrs with number \prcrng\num \else%write record to \kk \advance\kk1 \strnrs \ea\xdef\csname\the\kk\endcsname{\refer{} \nrs}\let\nrs\empty\init\num\prcrng\num \let\refer\word \fi \repeat\ifnum1<\n \advance\kk1 \strnrs \ea\xdef\csname\the\kk\endcsname{\word{} \nrs} \global\n\kk\fi}} % \def\prcrng#1{\init{#1}\def\prcrng##1{% \ifnum##1=\lst\else\ifnum##1=\slst \lst\slst\advance\slst1 \else \strnrs\init{##1}\fi\fi}} % \def\strnrs{\dif\lst\advance\dif-\frst \edef\nrs{\ifx\nrs\empty\else\nrs\sepn\fi \the\frst\ifnum0<\dif \ifnum1=\dif\sepn\the\lst \else\nobreak--\nobreak\the\lst \fi \fi}} % \def\splitwn#1 !#2 #3.{\def\word{#1 !#2}% \def\num{#3}} % \def\getdig#1 !#2 #3.{\def\dig{#2}} % \def\sortcs{\global\k0\global\pk\n \global\pkone\pk\global\advance\pkone1 %Invariant: 1:k non-cs; pk+1:n control seq-s \loop\global\advance\k1 \ifnum\k<\pkone \ea\ea\ea\getdig\csname\the\k\endcsname.% \if2\dig{\continuetrue \loop \ifnum\k=\pk\continuefalse \else\ea\ea\ea\getdig\csname\the\pk \endcsname.% \if2\dig \else\xch\k\pk\continuefalse \fi \fi\global\pkone\pk\global\advance\pk-1 \ifcontinue \repeat}% \fi \repeat}%Result\1:\pk non-cs, \pkone:\n cs % %Parameters: Ordering table \chardef\ota=32 \chardef\otA=32 \chardef\otaa=33 \chardef\otag=33 \chardef\otat=34 \chardef\otah=35 \chardef\otb=39 \chardef\otB=39 \chardef\otc=46 \chardef\otC=46 \chardef\otcc=47 \chardef\otcc=47 \chardef\otd=53 \chardef\otD=53 \chardef\ote=60 \chardef\otE=60 \chardef\otea=61 \chardef\oteg=62 \chardef\otet=63 \chardef\oteh=64 \chardef\otf=67 \chardef\otF=67 \chardef\otg=74 \chardef\otG=74 \chardef\oth=81 \chardef\otH=81 \chardef\oti=88 \chardef\otI=88 \chardef\otit=91 \chardef\otih=92 \chardef\otj=95 \chardef\otJ=95 \chardef\otjt=98 \chardef\otk=102 \chardef\otK=102 \chardef\otl=109 \chardef\otL=109 \chardef\otm=116 \chardef\otM=116 \chardef\otn=123 \chardef\otN=123 \chardef\oto=130 \chardef\otO=130 \chardef\otoa=131 \chardef\otog=132 \chardef\otot=133 \chardef\otoh=134 \chardef\otp=137 \chardef\otP=137 \chardef\otq=143 \chardef\otQ=143 \chardef\otr=150 \chardef\otR=150 \chardef\ots=157 \chardef\otS=157 \chardef\ott=164 \chardef\otT=164 \chardef\otu=171 \chardef\otU=171 \chardef\otut=174 \chardef\otuh=175 \chardef\otv=178 \chardef\otV=178 \chardef\otw=185 \chardef\otW=185 \chardef\otx=192 \chardef\otX=192 \chardef\otij=199 \chardef\otIJ=199 \chardef\oty=200 \chardef\otY=200 \chardef\otz=206 \chardef\otZ=206 %\endinput %cgl@rug.nl % %%%%%%%%%% heap sort macro %%%%%%%%%% %heapsort.tex Jan, 93 \newcount\n\newcount\lc\newcount\r \newcount\ic\newcount\uone \newcount\jc\newcount\jj\newcount\jjone \newif\ifgoon %Non-descending sorting \def\heapsort{%data in \1 to \n \r=\n\heap\ic=1{}% {\loop\ifnum\r>1{}\xch\ic\r \advance\r-1{}\sift\ic\r \repeat}} % \def\heap{%Transform \1..\n into heap \lc=\n\divide\lc2{}\advance\lc1{}% {\loop\ifnum\lc>1{}\advance\lc-1{}% \sift\lc\n\repeat}} % \def\sift#1#2{%#1, #2 counter variables \jj=#1\uone=#2\advance\uone1{}\goontrue {\loop\jc=\jj \advance\jj by\jj \ifnum\jj<\uone \jjone=\jj \advance\jjone1{}% \ifnum\jj<#2{}\cmpval\jj\jjone \ifnum2=\status\jj=\jjone\fi\fi \cmpval\jc\jj\ifnum2>\status\goonfalse\fi \else\goonfalse\fi \ifgoon\xch\jc\jj\repeat}} % \def\cmpval#1#2{%#1, #2 counter variables %Result: \status= 0, 1, 2 if % \val{#1} =, >, < \val{#2} \ea\let\ea\aone\csname\the#1\endcsname \ea\let\ea\atwo\csname\the#2\endcsname \cmp\aone\atwo} %\endinput %cgl@rug.nl % %%%%%%%%%% quick sort macro %%%%%%%%%% \newcount\low\newcount\up\newcount\m \def\quicksort{%Values given in %\low,...,\up are sorted, non-descending. %Parameters: \cmp, comparison. \ifnum\low<\up\else\brk\fi %\refval, a reference value selected at random. \m=\up\advance\m-\low%Size-1 of array part \ifnum10<\m\rnd\multiply\m\rndval \divide\m99{}\advance\m\low \xch\low\m \fi \ea\let\ea\refval\csname\the\low\endcsname \m=\low\k=\low\let\refvalcop=\refval {\loop\ifnum\k<\up\advance\k1{}% \ea\let\ea\oneqs\csname\the\k\endcsname \cmp\refval\oneqs\ifnum1=\status \global\advance\m1{}\xch\m\k\fi \let\refval=\refvalcop \repeat}\xch\low\m {\up=\m\advance\up-1{}\quicksort}% {\low=\m\advance\low1{}\quicksort}\krb} % \def\brk#1\krb{\fi}\def\krb{\relax} %\endinput %cgl@rug.nl % %%%%%%%%%% Example: heap sort %%%%%%%%%% \onecolumn \section{Appendix: Heap Sort} %Aug, 93, cgl@risc1.rug.nl The process consists of two main steps: creation of a heap, and sorting the heap. A sift operation is used in both. In comparison with my earlier release of the code in MAPS92.2, I adapted the notation with respect to sorting in {\em non-decreasing\/} order.\ftn{It is true that the reverse of the comparison operation would do, but it seemed more consistent to me to adapt the notation of the heap concept with the smallest elements at the bottom.} What is a heap? A sequence $a_1, a_2, \ldots, a_n$, is a heap if $a_k\ge a_{2k} \wedge a_k\ge a_{2k+1}, k=1, 2, \ldots, n\div2$, and because $a_{n+1}$ is undefined, the notation is simplified by defining $a_k>a_{n+1}, k= 1, 2, \ldots , n$. \\ For example, a tree and one of its heap representations of $2, 6, 7, 1, 3, 4$ read $$\setlength{\unitlength}{3ex} \vcenter{\noindent\hsize=18ex \begin{picture}(7,4.5)(0,-.5) \put(.5,.5){\circle{1}} \put(.5,.5){\makebox(0,0){1}} \put(2.5,.5){\circle{1}} \put(2.5,.5){\makebox(0,0){3}} \put(4.5,.5){\circle{1}} \put(4.5,.5){\makebox(0,0){4}} \put(1.5,2.5){\circle{1}} \put(1.5,2.5){\makebox(0,0){6}} \put(5.5,2.5){\circle{1}} \put(5.5,2.5){\makebox(0,0){7}} \put(3.5,3.5){\circle{1}} \put(3.5,3.5){\makebox(0,0){2}} \put(.9,1){\line(1,2){.5}} \put(2.1,1){\line(-1,2){.5}} \put(4.9,1){\line(1,2){.5}} \put(2,2.9){\line(2,1){1}} \put(5,2.9){\line(-2,1){1}} \end{picture}} \qquad\qquad \vcenter{\noindent\hsize=21ex \begin{picture}(7,5)(0,-.5) \put(.5,.5){\circle{1}} \put(.5,.5){\makebox(0,0){2}} \put(2.5,.5){\circle{1}} \put(2.5,.5){\makebox(0,0){3}} \put(4.5,.5){\circle{1}} \put(4.5,.5){\makebox(0,0){1}} \put(1.5,2.5){\circle{1}} \put(1.5,2.5){\makebox(0,0){6}} \put(5.5,2.5){\circle{1}} \put(5.5,2.5){\makebox(0,0){4}} \put(3.5,3.5){\circle{1}} \put(3.5,3.5){\makebox(0,0){7}} \put(.9,1){\line(1,2){.5}} \put(2.1,1){\line(-1,2){.5}} \put(4.9,1){\line(1,2){.5}} \put(2,2.9){\line(2,1){1}} \put(5,2.9){\line(-2,1){1}} \end{picture}} $$ % \subsection{The algorithm.} In a pseudo notation the algorithm, for sorting the array a[1:n], reads \def\PO#1{\mathop{\hbox{\bf#1}}} \def\P#1{\hbox{\bf#1}\,} {\obeylines \parindent=0pt \%heap creation $l:=n\PO{div}2+1; $ $\P{while} l\ne1 \PO{do} l:=l-1; sift(a, l, n)\PO{od}$ \%sorting $r:=n; $ $\P{while} r\ne1 \PO{do} (a[1], a[r]):=(a[r], a[1])\%exchange $ $\quad r:=r-1; sift(a, 1, r)\PO{od} $ \%sift \#1 through \#2 $j:=\#1 $ $\P{while} 2j\geq\#2 \wedge(a[j]<a[2j]\vee a[j]<a[2j+1])\PO{do} $ $\quad mi:=2j+\PO{if}a[2j]>a[2j+1]\PO{then}0\PO{else}1\PO{fi}$ $\quad exchange(a[j], a[mi])\,j:=mi\,\P{od}$ }%end scope \obeylines % \subsection{Encoding: Purpose.} Sorting values given in an array. % \subsection{Encoding: Input.} The values are stored in the control sequences \verb|\1|, \ldots, \verb|\|$\langle n\rangle$. The counter \verb|\n| must contain the value $\langle n\rangle$. The parameter for comparison, \verb|\cmp|, must be \verb|\let|-equal to \verb|\cmpn|, for numerical comparison, to \verb|\cmpw|, for word comparison, to \verb|\cmpaw|, for word comparison obeying the ASCII ordering, or to a comparison macro of your own. (The latter macro variants, and in general the common definitions for \verb|\heapsort|, and \verb|\quicksort|, are supplied in the file \verb|sort.tex|, see van der Laan (1993).) % \subsection{Encoding: Output.} The sorted array \verb|\1|, \verb|\2|, \ldots \verb|\|$\langle n\rangle$, with \verb|\val1| $\le$ \verb|\val2| $\le$ \ldots $\le$ \verb|\val|$\langle n\rangle$. %\ftn{And {\tt\char92% %def\char92val\#1$\{$\char92csname\#1\char92endcsname$\}$.}} % \subsection{Encoding: Source.} \begin{verbatim} %heapsort.tex Jan, 93 \newcount\n\newcount\lc\newcount\r\newcount\ic\newcount\uone \newcount\jc\newcount\jj\newcount\jjone \newif\ifgoon %Non-descending sorting \def\heapsort{%data in \1 to \n \r\n\heap\ic1 {\loop\ifnum1<\r \xch\ic\r \advance\r-1 \sift\ic\r\repeat}} % \def\heap{%Transform \1..\n into heap \lc\n\divide\lc2{}\advance\lc1 {\loop\ifnum1<\lc\advance\lc-1 \sift\lc\n\repeat}} % \def\sift#1#2{%#1, #2 counter variables \jj#1\uone#2\advance\uone1 \goontrue {\loop\jc\jj \advance\jj\jj \ifnum\jj<\uone \jjone\jj \advance\jjone1 \ifnum\jj<#2 \cmpval\jj\jjone \ifnum2=\status\jj\jjone\fi \fi\cmpval\jc\jj\ifnum2>\status\goonfalse\fi \else\goonfalse \fi \ifgoon\xch\jc\jj\repeat}} % \def\cmpval#1#2{%#1, #2 counter variables %Result: \status= 0, 1, 2 if %values pointed by % #1 =, >, < #2 \ea\let\ea\aone\csname\the#1\endcsname \ea\let\ea\atwo\csname\the#2\endcsname \cmp\aone\atwo} \endinput %cgl@risc1.rug.nl \end{verbatim} % \subsection{Explanation: {\tt\char92heapsort}.} The values given in \verb|\1,...\|$\langle n\rangle$, are sorted in non-descending order. \subsection{Explanation: {\tt\char92heap}.} The values given in \verb|\1|, \ldots, \verb|\|$\langle n\rangle$, are rearranged into a heap. \subsection{Explanation: {\tt\char92sift}.} The first element denoted by the first (counter) argument has disturbed the heap. Sift rearranges the part of the array denoted by its two arguments, such that the heap property holds again. \subsection{Explanation: {\tt\char92cmpval}.} The values denoted by the counter values, supplied as arguments, are compared. % \subsection{Examples of use: Numbers, words.} %, and accented words) After \verb=\input heap \input sort= \begin{verbatim} \def\1{314}\def\2{1}\def\3{27}\n3 \let\cmp\cmpn\heapsort \begin{quote}\prtn,\end{quote} % \def\1{ab}\def\2{c}\def\3{aa}\n3 \let\cmp\cmpaw\heapsort \begin{quote}\prtw,\end{quote} and \def\1{j\ij}\def\2{ge\"urm}\def\3{gar\c con}\def\4{\'el\`eve}\n4 \let\cmp\cmpw {\accdef\heapsort} \begin{quote}\prtw\end{quote} \end{verbatim} yields\ftn{{\tt\char92accdef} suitably redefines the accents within this scope.} \def\1{314}\def\2{1}\def\3{27}\n=3 {\let\cmp\cmpn\heapsort \begin{quote}\prtn,\end{quote} % \def\1{ab}\def\2{c}\def\3{aa}\n=3 \let\cmp\cmpaw\heapsort \begin{quote}\prtw,\end{quote} and \def\1{j\ij}\def\2{ge\"urm}\def\3{gar\c con}\def\4{\'el\`eve}\n=4 \let\cmp=\cmpw{\accdef\heapsort} \begin{quote}\prtw.\end{quote} } % \clearpage %%%%%%%%%% Example: quick sort %%%%%%%%%% \section{Appendix: Quick Sort} The quick sort algorithm has been discussed in many places. %, %for example \cite{dek73}. Here the following code due to Bentley %\cite{jb86}, p.~112, has been transliterated.\footnote{L, U have been changed in the \TeX\ code into low, up.} \begin{verbatim} procedure QSort(L,U) if L<U then Swap(X[l], X[RandInt(L,U)]) T:=X[L] M:=L for I:=L+1 to U do if X[I]<T M:=M+1 Swap(X[M], X[I]) fi od Swap(X[L], X[M]) QSort(L, M-1) QSort(M+1, U) fi \end{verbatim} % \subsection{Encoding: Purpose.} Sorting of the values given in the array \verb|\|$\langle low\rangle$, \ldots, \verb|\|$\langle up\rangle$. \subsection{Encoding: Input.} The values are stored in \verb|\|$\langle low\rangle$, \ldots, \verb|\|$\langle up\rangle$, with $1\le low\le up\le n$. The parameter for comparison, \verb|\cmp|, must be \verb|\let|-equal to \verb|\cmpn|, for number comparison, to \verb|\cmpw|, for word comparison, to \verb|\cmpaw|, for word comparison obeying the ASCII ordering, or to a comparison macro of your own. (The latter macros, and in general the common definitions for \verb|\heapsort|, and \verb|\quicksort|, are supplied in the file \verb|sort.tex|, see van der Laan (1993).) % \subsection{Encoding: Output.} The sorted array \verb|\|$\langle low\rangle$, \ldots \verb|\|$\langle up\rangle$, with \verb|\val|$\langle low\rangle \le \dots \le{}$ \verb|\val|$\langle up\rangle$. % \subsection{Encoding: Source.} \begin{verbatim} %quick.tex Jan 93 \newcount\low\newcount\up\newcount\m \def\quicksort{%Values given in \low,...,\up are sorted, non-descending. %Parameters: \cmp, comparison. \ifnum\low<\up\else\brk\fi %\refval, a reference value selected at random. \m\up\advance\m-\low%Size-1 of array part \ifnum10<\m\rnd\multiply\m\rndval \divide\m99 \advance\m\low \xch\low\m \fi \ea\let\ea\refval\csname\the\low\endcsname \m\low\k\low\let\refvalcop\refval {\loop\ifnum\k<\up\advance\k1 \ea\let\ea\oneqs\csname\the\k\endcsname \cmp\refval\oneqs\ifnum1=\status\global\advance\m1 \xch\m\k\fi \let\refval\refvalcop \repeat}\xch\low\m {\up\m\advance\up-1 \quicksort}{\low\m\advance\low1 \quicksort}\krb} % \def\brk#1\krb{\fi}\def\krb{\relax} \endinput %cgl@risc1.rug.nl \end{verbatim} \subsection{Explanation.} At each level the array is partitioned into two parts. After partitioning the left part contains values less than the reference value and the right part contains values greater than or equal to the reference value. Each part is again partitioned via a recursive call of the macro. The array is sorted when all parts are partitioned. In the \TeX\ encoding the reference value as estimate for the mean value is determined via a random selection of one of the elements. The random number is mapped into the range [$\,low:up\,$], via the linear transformation $\hbox{\tt\char92low}+(\hbox{\tt\char92up}-\hbox{\tt\char92low})* \hbox{\tt\char92rndval}/99$.\ftn{Note that the number is guaranteed within the range.} The termination of the recursion is encoded in a \TeX\ peculiar way. First, I encoded the infinite loop. Then I inserted the condition for termination with the \verb|\fi| on the same line, and not enclosing the main part of the macro. On termination the invocation \verb|\brk| gobbles up all the tokens at that level up to its separator \verb|\krb|, and inserts its replacement text\Dash a new \verb|\fi|\Dash % to compensate for the gobbled \verb|\fi|. % \subsection{Examples: Numbers, words.} After \verb=\input quick \input sort= \begin{verbatim} \def\1{314}\def\2{1}\def\3{27}\n3 \low1\up\n\let\cmp\cmpn \quicksort \begin{quote}\prtn,\end{quote} % \def\1{ab}\def\2{c}\def\3{aa}\def\4{\ij}\def\5{ik}\def\6{z}\def\7{a}\n7 \low1\up\n\let\cmp\cmpw \quicksort \begin{quote}\prtw,\end{quote} and \def\1{j\ij}\def\2{ge\"urm}\def\3{gar\c con}\def\4{\'el\`eve}\n4 \low1\up\n\let\cmp\cmpw {\accdef\quicksort} \begin{quote}\prtw.\end{quote} \end{verbatim} yields\ftn{{\tt\char92accdef} suitably redefines the accents within this scope.} \def\1{314}\def\2{1}\def\3{27}\n3 {\low1\up\n\let\cmp\cmpn \quicksort \begin{quote}\prtn,\end{quote} % \def\1{ab}\def\2{c}\def\3{aa} \def\4{\ij}\def\5{ik}\def\6{z}\def\7{a}\n7 \low1\up\n\let\cmp\cmpw \quicksort \begin{quote}\prtw,\end{quote} and \def\1{j\ij}\def\2{ge\"urm}\def\3{gar\c con} \def\4{\'el\`eve}\n=4 \low=1\up=\n\let\cmp=\cmpw {\accdef\quicksort} \begin{quote}\prtw.\end{quote} } %end appendices \end{document}