Phil Lucht Math & Physics Archive
Home / Math and Physics Files / Math / Scheid and numerical / Numerical Recipes in Fortran

f8-2

PDF · 5 pages · 49.3 KB
Open PDF file

Excerpt of pages 323-327 of Numerical Recipes in Fortran 77 (Cambridge University Press, 1986-1992), Chapter 8 on sorting. It ends the Shell sort routine, then presents Quicksort: partitioning, median-of-three pivot choice, sentinels, a stack for subarrays, and insertion sort for small pieces. It lists the Fortran subroutines sort and sort2 (which rearranges a second array too) and begins Heapsort (8.3).

AI-written summary; may contain errors.

Extracted text (machine-read; may contain errors)
8.2Quicksort 323Sample page from NUMERICAL RECIPES IN FORTRAN 77: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43064-X) Copyright (C) 1986-1992 by Cambridge University Press.Programs Copyright (C) 1986-1992 by Numerical Recipes Software. Permission is granted for internet users to make one paper copy for their own personal use. Further reproduction, or any copyin g of machine- readable files (including this one) to any servercomputer, is strictly prohibited. To order Numerical Recipes booksor CDROMs, v isit website http://www.nr.com or call 1-800-872-7423 (North America only),or send email to [email protected] (outside North Amer ica).For “randomly” ordered data, the operations count goes approximatelyas N1.25,a t least for N< 60000.F o r N> 50, however, Quicksort is generally faster. The program follows: SUBROUTINE shell(n,a) INTEGER n REAL a(n) Sorts an array a(1:n) into ascending numerical order by Shell’s method (diminishing in- crement sort). nis input; ais replaced on output by its sorted rearrangement. INTEGER i,j,incREAL vinc=1 Determine the starting increment. 1 inc=3*inc+1 if(inc.le.n)goto 1 2 continue Loop over the partial sorts. inc=inc/3 do 11i=inc+1,n Outer loop of straight insertion. v=a(i)j=i 3 if(a(j-inc).gt.v)then Inner loop of straight insertion. a(j)=a(j-inc)j=j-incif(j.le.inc)goto 4 goto 3 endif 4 a(j)=v enddo 11 if(inc.gt.1)goto 2 returnEND CITED REFERENCES AND FURTHER READING: Knuth,D.E. 1973, SortingandSearching ,v ol.3of TheArtofComputerProgramming (Reading, MA: Addison-Wesley),§5.2.1. [1] Sedgewick, R. 1988, Algorithms , 2nd ed. (Reading, MA: Addison-Wesley), Chapter 8. 8.2 Quicksort Quicksort is, on most machines, on average, for large N, the fastest known sorting algorithm. It is a “partition-exchange” sorting method: A “partitioning element” ais selected from the array. Then by pairwise exchangesof elements, the originalarrayispartitionedintotwosubarrays. Attheendofaroundofpartitioning, the element ais in its final place in the array. All elements in the left subarray are ≤a, while all elements in the right subarray are ≥a. The process is then repeated on the left and right subarrays independently, and so on. The partitioning process is carried out by selecting some element, say the leftmost, as the partitioning element a. Scan a pointer up the array until you find an element >a, and then scan another pointer down from the end of the array until you find an element <a. These two elements are clearly out of place for the final partitioned array, so exchange them. Continue this process until the pointers 324 Chapter8. SortingSample page from NUMERICAL RECIPES IN FORTRAN 77: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43064-X) Copyright (C) 1986-1992 by Cambridge University Press.Programs Copyright (C) 1986-1992 by Numerical Recipes Software. Permission is granted for internet users to make one paper copy for their own personal use. Further reproduction, or any copyin g of machine- readable files (including this one) to any servercomputer, is strictly prohibited. To order Numerical Recipes booksor CDROMs, v isit website http://www.nr.com or call 1-800-872-7423 (North America only),or send email to [email protected] (outside North Amer ica).cross. This is the right place to insert a, and that roundof partitioningis done. The question of the best strategy when an element is equal to the partitioning elementis subtle; we refer you to Sedgewick [1]for a discussion. (Answer: You should stop and do an exchange.) Quicksort requires an auxiliary array of storage, of length 2l o g2N, which it uses as a push-down stack for keeping track of the pending subarrays. When a subarray has gotten down to some size M, it becomes faster to sort it by straight insertion( §8.1),so wewill dothis. Theoptimalsettingof Mis machinedependent, but M =7is not too far wrong. Some people advocate leaving the short subarrays unsorted until the end, and then doing one giant insertion sort at the end. Sinceeach element moves at most 7 places, this is just as efficient as doing the sorts immediately,andsaves onthe overhead. However,onmodernmachineswithpaged memory,thereisincreasedoverheadwhendealingwithalargearrayallatonce. Wehave not found any advantage in saving the insertion sorts till the end. As already mentioned, Quicksort’s averagerunning time is fast, but its worst caserunningtime can be veryslow: For the worst case it is, in fact, an N 2method! And for the most straightforward implementation of Quicksort it turns out that the worst case is achieved for an input array that is already in order! This ordering of the input array might easily occur in practice. One way to avoid this is to use a little random number generator to choose a random element as the partitioning element. Anotheris to use instead the median of the first, middle,and last elementsof the current subarray. The great speed of Quicksort comes from the simplicity and efficiency of its innerloop. Simplyaddingoneunnecessarytest(forexample,atestthatyourpointerhas not moved off the end of the array) can almost double the running time! One avoids such unnecessary tests by placing “sentinels” at either end of the subarray being partitioned. The leftmost sentinel is ≤a, the rightmost ≥a. With the “median-of-three”selection of a partitioning element, we can use the two elements that were not the median to be the sentinels for that subarray. Our implementation closely follows [1]: SUBROUTINE sort(n,arr) INTEGER n,M,NSTACK REAL arr(n)PARAMETER (M=7,NSTACK=50) Sorts an array arr(1:n) into ascending numerical order using the Quicksort algorithm. n is input; arr is replaced on output by its sorted rearrangement. Parameters: Mis the size of subarrays sorted by straight insertion and NSTACK is the required auxiliary storage. INTEGER i,ir,j,jstack,k,l,istack(NSTACK) REAL a,tempjstack=0l=1 ir=n 1 if(ir-l.lt.M)then Insertion sort when subarray small enough. do 12j=l+1,ir a=arr(j) do11i=j-1,l,-1 if(arr(i).le.a)goto 2arr(i+1)=arr(i) enddo 11 i=l-1 2 arr(i+1)=a enddo 12 8.2Quicksort 325Sample page from NUMERICAL RECIPES IN FORTRAN 77: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43064-X) Copyright (C) 1986-1992 by Cambridge University Press.Programs Copyright (C) 1986-1992 by Numerical Recipes Software. Permission is granted for internet users to make one paper copy for their own personal use. Further reproduction, or any copyin g of machine- readable files (including this one) to any servercomputer, is strictly prohibited. To order Numerical Recipes booksor CDROMs, v isit website http://www.nr.com or call 1-800-872-7423 (North America only),or send email to [email protected] (outside North Amer ica).if(jstack.eq.0)return ir=istack(jstack) Pop stack and begin a new round of partitioning. l=istack(jstack-1) jstack=jstack-2 else k=(l+ir)/2 Choose median of left, center, and right elements as par- titioning element a.A l s or e a r r a n g es ot h a t a(l)≤ a(l+1) ≤a(ir) .temp=arr(k) arr(k)=arr(l+1)arr(l+1)=temp if(arr(l).gt.arr(ir))then temp=arr(l)arr(l)=arr(ir)arr(ir)=temp endif if(arr(l+1).gt.arr(ir))then temp=arr(l+1) arr(l+1)=arr(ir) arr(ir)=temp endifif(arr(l).gt.arr(l+1))then temp=arr(l) arr(l)=arr(l+1)arr(l+1)=temp endif i=l+1 Initialize pointers for partitioning. j=ira=arr(l+1) Partitioning element. 3 continue Beginning of innermost loop. i=i+1 Scan up to find element >a. if(arr(i).lt.a)goto 3 4 continue j=j-1 Scan down to find element <a. if(arr(j).gt.a)goto 4if(j.lt.i)goto 5 Pointers crossed. Exit with partitioning complete. temp=arr(i) Exchange elements. arr(i)=arr(j)arr(j)=tempgoto 3 End of innermost loop. 5 arr(l+1)=arr(j) Insert partitioning element. arr(j)=ajstack=jstack+2 Push pointers to larger subarray on stack, process smaller subarray immediately. if(jstack.gt.NSTACK)pause ’NSTACK too small in sort’if(ir-i+1.ge.j-l)then istack(jstack)=ir istack(jstack-1)=i ir=j-1 else istack(jstack)=j-1 istack(jstack-1)=ll=i endif endif goto 1END As usual you can move any other arrays around at the same time as you sort arr. At the risk of being repetitious: 326 Chapter8. SortingSample page from NUMERICAL RECIPES IN FORTRAN 77: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43064-X) Copyright (C) 1986-1992 by Cambridge University Press.Programs Copyright (C) 1986-1992 by Numerical Recipes Software. Permission is granted for internet users to make one paper copy for their own personal use. Further reproduction, or any copyin g of machine- readable files (including this one) to any servercomputer, is strictly prohibited. To order Numerical Recipes booksor CDROMs, v isit website http://www.nr.com or call 1-800-872-7423 (North America only),or send email to [email protected] (outside North Amer ica).SUBROUTINE sort2(n,arr,brr) INTEGER n,M,NSTACK REAL arr(n),brr(n) PARAMETER (M=7,NSTACK=50) Sorts an array arr(1:n) into ascending order using Quicksort, while making the corre- sponding rearrangement of the array brr(1:n) . INTEGER i,ir,j,jstack,k,l,istack(NSTACK)REAL a,b,tempjstack=0 l=1 ir=n 1 if(ir-l.lt.M)then Insertion sort when subarray small enough. do 12j=l+1,ir a=arr(j) b=brr(j)do 11i=j-1,l,-1 if(arr(i).le.a)goto 2 arr(i+1)=arr(i)brr(i+1)=brr(i) enddo 11 i=l-1 2 arr(i+1)=a brr(i+1)=b enddo 12 if(jstack.eq.0)return ir=istack(jstack) Pop stack and begin a new round of partitioning. l=istack(jstack-1) jstack=jstack-2 else k=(l+ir)/2 Choose median of left, center and right elements as par- titioning element a.A l s or e a r r a n g es ot h a t a(l)≤ a(l+1) ≤a(ir) .temp=arr(k) arr(k)=arr(l+1)arr(l+1)=temptemp=brr(k) brr(k)=brr(l+1) brr(l+1)=tempif(arr(l).gt.arr(ir))then temp=arr(l) arr(l)=arr(ir) arr(ir)=temptemp=brr(l) brr(l)=brr(ir) brr(ir)=temp endifif(arr(l+1).gt.arr(ir))then temp=arr(l+1) arr(l+1)=arr(ir)arr(ir)=temp temp=brr(l+1) brr(l+1)=brr(ir)brr(ir)=temp endif if(arr(l).gt.arr(l+1))then temp=arr(l)arr(l)=arr(l+1) arr(l+1)=temp temp=brr(l)brr(l)=brr(l+1)brr(l+1)=temp endif i=l+1 Initialize pointers for partitioning. j=ira=arr(l+1) Partitioning element. b=brr(l+1) 8.3Heapsort 327Sample page from NUMERICAL RECIPES IN FORTRAN 77: THE ART OF SCIENTIFIC COMPUTING (ISBN 0-521-43064-X) Copyright (C) 1986-1992 by Cambridge University Press.Programs Copyright (C) 1986-1992 by Numerical Recipes Software. Permission is granted for internet users to make one paper copy for their own personal use. Further reproduction, or any copyin g of machine- readable files (including this one) to any servercomputer, is strictly prohibited. To order Numerical Recipes booksor CDROMs, v isit website http://www.nr.com or call 1-800-872-7423 (North America only),or send email to [email protected] (outside North Amer ica).3 continue Beginning of innermost loop. i=i+1 Scan up to find element >a. if(arr(i).lt.a)goto 3 4 continue j=j-1 Scan down to find element <a. if(arr(j).gt.a)goto 4 if(j.lt.i)goto 5 Pointers crossed. Exit with partitioning complete. temp=arr(i) Exchange elements of both arrays. arr(i)=arr(j) arr(j)=temp temp=brr(i)brr(i)=brr(j)brr(j)=temp goto 3 End of innermost loop. 5 arr(l+1)=arr(j) Insert partitioning element in both arrays. arr(j)=a brr(l+1)=brr(j) brr(j)=bjstack=jstack+2 Push pointers to larger subarray on stack, process smaller subarray immediately. if(jstack.gt.NSTACK)pause ’NSTACK too small in sort2’ if(ir-i+1.ge.j-l)then istack(jstack)=ir istack(jstack-1)=i ir=j-1 else istack(jstack)=j-1 istack(jstack-1)=l l=i endif endif goto 1END You could, in principle, rearrange any number of additional arrays along with brr, but this becomes wasteful as the number of such arrays becomes large. The preferred technique is to make use of an index table, as described in §8.4. CITED REFERENCES AND FURTHER READING: Sedgewick, R. 1978, Communications of the ACM , vol. 21, pp. 847–857. [1] 8.3 Heapsort While usually not quite as fast as Quicksort, Heapsort is one of our favorite sorting routines. It is a true “in-place” sort, requiring no auxiliary storage. It is an Nlog2Nprocess,notonlyonaverage,butalsofortheworst-caseorderofinputdata. Infact, its worst case is only20 percentor so worse thanits averagerunningtime. It is beyondourscope togivea completeexpositiononthe theoryofHeapsort. We will mention the general principles, then let you refer to the references [1,2],o r analyze the program yourself, if you want to understand the details. A set of Nnumbers ai,i =1 ,...,N, is said to form a “heap” if it satisfies the relation aj/2≥ajfor 1≤j/2<j≤N (8.3.1 )