OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
sortrx.f
Go to the documentation of this file.
1 C From Leonard J. Moss of SLAC:
2 
3 C Here's a hybrid QuickSort I wrote a number of years ago. It's
4 C based on suggestions in Knuth, Volume 3, and performs much better
5 C than a pure QuickSort on short or partially ordered input arrays.
6 
7  SUBROUTINE sortrx(N,DATA,INDEX)
8 C===================================================================
9 C
10 C SORTRX -- SORT, Real input, indeX output
11 C
12 C
13 C Input: N INTEGER
14 C DATA REAL
15 C
16 C Output: INDEX INTEGER (DIMENSION N)
17 C
18 C This routine performs an in-memory sort of the first N elements of
19 C array DATA, returning into array INDEX the indices of elements of
20 C DATA arranged in ascending order. Thus,
21 C
22 C DATA(INDEX(1)) will be the smallest number in array DATA;
23 C DATA(INDEX(N)) will be the largest number in DATA.
24 C
25 C The original data is not physically rearranged. The original order
26 C of equal input values is not necessarily preserved.
27 C
28 C===================================================================
29 C
30 C SORTRX uses a hybrid QuickSort algorithm, based on several
31 C suggestions in Knuth, Volume 3, Section 5.2.2. In particular, the
32 C "pivot key" [my term] for dividing each subsequence is chosen to be
33 C the median of the first, last, and middle values of the subsequence;
34 C and the QuickSort is cut off when a subsequence has 9 or fewer
35 C elements, and a straight insertion sort of the entire array is done
36 C at the end. The result is comparable to a pure insertion sort for
37 C very short arrays, and very fast for very large arrays (of order 12
38 C micro-sec/element on the 3081K for arrays of 10K elements). It is
39 C also not subject to the poor performance of the pure QuickSort on
40 C partially ordered data.
41 C
42 C Created: 15 Jul 1986 Len Moss
43 C
44 C===================================================================
45 
46  INTEGER N,INDEX(N)
47  REAL DATA(N)
48 
49  INTEGER LSTK(31),RSTK(31),ISTK
50  INTEGER L,R,I,J,P,INDEXP,INDEXT
51  REAL DATAP
52 
53 C QuickSort Cutoff
54 C
55 C Quit QuickSort-ing when a subsequence contains M or fewer
56 C elements and finish off at end with straight insertion sort.
57 C According to Knuth, V.3, the optimum value of M is around 9.
58 
59  INTEGER M
60  parameter(m=9)
61 
62 C===================================================================
63 C
64 C Make initial guess for INDEX
65 
66  DO 50 i=1,n
67  index(i)=i
68  50 CONTINUE
69 
70 C If array is short, skip QuickSort and go directly to
71 C the straight insertion sort.
72 
73  IF (n.LE.m) GOTO 900
74 
75 C===================================================================
76 C
77 C QuickSort
78 C
79 C The "Qn:"s correspond roughly to steps in Algorithm Q,
80 C Knuth, V.3, PP.116-117, modified to select the median
81 C of the first, last, and middle elements as the "pivot
82 C key" (in Knuth's notation, "K"). Also modified to leave
83 C data in place and produce an INDEX array. To simplify
84 C comments, let DATA[I]=DATA(INDEX(I)).
85 
86 C Q1: Initialize
87  istk=0
88  l=1
89  r=n
90 
91  200 CONTINUE
92 
93 C Q2: Sort the subsequence DATA[L]..DATA[R].
94 C
95 C At this point, DATA[l] <= DATA[m] <= DATA[r] for all l < L,
96 C r > R, and L <= m <= R. (First time through, there is no
97 C DATA for l < L or r > R.)
98 
99  i=l
100  j=r
101 
102 C Q2.5: Select pivot key
103 C
104 C Let the pivot, P, be the midpoint of this subsequence,
105 C P=(L+R)/2; then rearrange INDEX(L), INDEX(P), and INDEX(R)
106 C so the corresponding DATA values are in increasing order.
107 C The pivot key, DATAP, is then DATA[P].
108 
109  p=(l+r)/2
110  indexp=index(p)
111  datap=DATA(indexp)
112 
113  IF (DATA(index(l)) .GT. datap) THEN
114  index(p)=index(l)
115  index(l)=indexp
116  indexp=index(p)
117  datap=DATA(indexp)
118  ENDIF
119 
120  IF (datap .GT. DATA(index(r))) THEN
121  IF (DATA(index(l)) .GT. DATA(index(r))) THEN
122  index(p)=index(l)
123  index(l)=index(r)
124  ELSE
125  index(p)=index(r)
126  ENDIF
127  index(r)=indexp
128  indexp=index(p)
129  datap=DATA(indexp)
130  ENDIF
131 
132 C Now we swap values between the right and left sides and/or
133 C move DATAP until all smaller values are on the left and all
134 C larger values are on the right. Neither the left or right
135 C side will be internally ordered yet; however, DATAP will be
136 C in its final position.
137 
138  300 CONTINUE
139 
140 C Q3: Search for datum on left >= DATAP
141 C
142 C At this point, DATA[L] <= DATAP. We can therefore start scanning
143 C up from L, looking for a value >= DATAP (this scan is guaranteed
144 C to terminate since we initially placed DATAP near the middle of
145 C the subsequence).
146 
147  i=i+1
148  IF (DATA(index(i)).LT.datap) GOTO 300
149 
150  400 CONTINUE
151 
152 C Q4: Search for datum on right <= DATAP
153 C
154 C At this point, DATA[R] >= DATAP. We can therefore start scanning
155 C down from R, looking for a value <= DATAP (this scan is guaranteed
156 C to terminate since we initially placed DATAP near the middle of
157 C the subsequence).
158 
159  j=j-1
160  IF (DATA(index(j)).GT.datap) GOTO 400
161 
162 C Q5: Have the two scans collided?
163 
164  IF (i.LT.j) THEN
165 
166 C Q6: No, interchange DATA[I] <--> DATA[J] and continue
167 
168  indext=index(i)
169  index(i)=index(j)
170  index(j)=indext
171  GOTO 300
172  ELSE
173 
174 C Q7: Yes, select next subsequence to sort
175 C
176 C At this point, I >= J and DATA[l] <= DATA[I] == DATAP <= DATA[r],
177 C for all L <= l < I and J < r <= R. If both subsequences are
178 C more than M elements long, push the longer one on the stack and
179 C go back to QuickSort the shorter; if only one is more than M
180 C elements long, go back and QuickSort it; otherwise, pop a
181 C subsequence off the stack and QuickSort it.
182 
183  IF (r-j .GE. i-l .AND. i-l .GT. m) THEN
184  istk=istk+1
185  lstk(istk)=j+1
186  rstk(istk)=r
187  r=i-1
188  ELSE IF (i-l .GT. r-j .AND. r-j .GT. m) THEN
189  istk=istk+1
190  lstk(istk)=l
191  rstk(istk)=i-1
192  l=j+1
193  ELSE IF (r-j .GT. m) THEN
194  l=j+1
195  ELSE IF (i-l .GT. m) THEN
196  r=i-1
197  ELSE
198 C Q8: Pop the stack, or terminate QuickSort if empty
199  IF (istk.LT.1) GOTO 900
200  l=lstk(istk)
201  r=rstk(istk)
202  istk=istk-1
203  ENDIF
204  GOTO 200
205  ENDIF
206 
207  900 CONTINUE
208 
209 C===================================================================
210 C
211 C Q9: Straight Insertion sort
212 
213  DO 950 i=2,n
214  IF (DATA(index(i-1)) .GT. DATA(index(i))) THEN
215  indexp=index(i)
216  datap=DATA(indexp)
217  p=i-1
218  920 CONTINUE
219  index(p+1) = index(p)
220  p=p-1
221  IF (p.GT.0) THEN
222  IF (DATA(index(p)).GT.datap) GOTO 920
223  ENDIF
224  index(p+1) = indexp
225  ENDIF
226  950 CONTINUE
227 
228 C===================================================================
229 C
230 C All done
231 
232  END
README for MOD_PR03(V6.1.0) 2. POINTS OF CONTACT it can be either SDP Toolkit or MODIS Packet for Terra input files The orbit validation configuration parameter(LUN 600281) must be either "TRUE" or "FALSE". It needs to be "FALSE" when running in Near Real Time mode
subroutine sortrx(N, DATA, INDEX)
Definition: sortrx.f:8