Source file src/pkg/sort/sort.go
1
2
3
4
5
6
7 package sort
8
9
10
11
12 type Interface interface {
13
14 Len() int
15
16
17 Less(i, j int) bool
18
19 Swap(i, j int)
20 }
21
22 func min(a, b int) int {
23 if a < b {
24 return a
25 }
26 return b
27 }
28
29
30 func insertionSort(data Interface, a, b int) {
31 for i := a + 1; i < b; i++ {
32 for j := i; j > a && data.Less(j, j-1); j-- {
33 data.Swap(j, j-1)
34 }
35 }
36 }
37
38
39
40 func siftDown(data Interface, lo, hi, first int) {
41 root := lo
42 for {
43 child := 2*root + 1
44 if child >= hi {
45 break
46 }
47 if child+1 < hi && data.Less(first+child, first+child+1) {
48 child++
49 }
50 if !data.Less(first+root, first+child) {
51 return
52 }
53 data.Swap(first+root, first+child)
54 root = child
55 }
56 }
57
58 func heapSort(data Interface, a, b int) {
59 first := a
60 lo := 0
61 hi := b - a
62
63
64 for i := (hi - 1) / 2; i >= 0; i-- {
65 siftDown(data, i, hi, first)
66 }
67
68
69 for i := hi - 1; i >= 0; i-- {
70 data.Swap(first, first+i)
71 siftDown(data, lo, i, first)
72 }
73 }
74
75
76
77
78
79 func medianOfThree(data Interface, a, b, c int) {
80 m0 := b
81 m1 := a
82 m2 := c
83
84 if data.Less(m1, m0) {
85 data.Swap(m1, m0)
86 }
87 if data.Less(m2, m1) {
88 data.Swap(m2, m1)
89 }
90 if data.Less(m1, m0) {
91 data.Swap(m1, m0)
92 }
93
94 }
95
96 func swapRange(data Interface, a, b, n int) {
97 for i := 0; i < n; i++ {
98 data.Swap(a+i, b+i)
99 }
100 }
101
102 func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
103 m := lo + (hi-lo)/2
104 if hi-lo > 40 {
105
106 s := (hi - lo) / 8
107 medianOfThree(data, lo, lo+s, lo+2*s)
108 medianOfThree(data, m, m-s, m+s)
109 medianOfThree(data, hi-1, hi-1-s, hi-1-2*s)
110 }
111 medianOfThree(data, lo, m, hi-1)
112
113
114
115
116
117
118
119
120
121
122
123 pivot := lo
124 a, b, c, d := lo+1, lo+1, hi, hi
125 for {
126 for b < c {
127 if data.Less(b, pivot) {
128 b++
129 } else if !data.Less(pivot, b) {
130 data.Swap(a, b)
131 a++
132 b++
133 } else {
134 break
135 }
136 }
137 for b < c {
138 if data.Less(pivot, c-1) {
139 c--
140 } else if !data.Less(c-1, pivot) {
141 data.Swap(c-1, d-1)
142 c--
143 d--
144 } else {
145 break
146 }
147 }
148 if b >= c {
149 break
150 }
151
152 data.Swap(b, c-1)
153 b++
154 c--
155 }
156
157 n := min(b-a, a-lo)
158 swapRange(data, lo, b-n, n)
159
160 n = min(hi-d, d-c)
161 swapRange(data, c, hi-n, n)
162
163 return lo + b - a, hi - (d - c)
164 }
165
166 func quickSort(data Interface, a, b, maxDepth int) {
167 for b-a > 7 {
168 if maxDepth == 0 {
169 heapSort(data, a, b)
170 return
171 }
172 maxDepth--
173 mlo, mhi := doPivot(data, a, b)
174
175
176 if mlo-a < b-mhi {
177 quickSort(data, a, mlo, maxDepth)
178 a = mhi
179 } else {
180 quickSort(data, mhi, b, maxDepth)
181 b = mlo
182 }
183 }
184 if b-a > 1 {
185 insertionSort(data, a, b)
186 }
187 }
188
189
190
191
192 func Sort(data Interface) {
193
194 n := data.Len()
195 maxDepth := 0
196 for i := n; i > 0; i >>= 1 {
197 maxDepth++
198 }
199 maxDepth *= 2
200 quickSort(data, 0, n, maxDepth)
201 }
202
203 type reverse struct {
204
205
206 Interface
207 }
208
209
210 func (r reverse) Less(i, j int) bool {
211 return r.Interface.Less(j, i)
212 }
213
214
215 func Reverse(data Interface) Interface {
216 return &reverse{data}
217 }
218
219
220 func IsSorted(data Interface) bool {
221 n := data.Len()
222 for i := n - 1; i > 0; i-- {
223 if data.Less(i, i-1) {
224 return false
225 }
226 }
227 return true
228 }
229
230
231
232
233 type IntSlice []int
234
235 func (p IntSlice) Len() int { return len(p) }
236 func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
237 func (p IntSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
238
239
240 func (p IntSlice) Sort() { Sort(p) }
241
242
243 type Float64Slice []float64
244
245 func (p Float64Slice) Len() int { return len(p) }
246 func (p Float64Slice) Less(i, j int) bool { return p[i] < p[j] || isNaN(p[i]) && !isNaN(p[j]) }
247 func (p Float64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
248
249
250 func isNaN(f float64) bool {
251 return f != f
252 }
253
254
255 func (p Float64Slice) Sort() { Sort(p) }
256
257
258 type StringSlice []string
259
260 func (p StringSlice) Len() int { return len(p) }
261 func (p StringSlice) Less(i, j int) bool { return p[i] < p[j] }
262 func (p StringSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
263
264
265 func (p StringSlice) Sort() { Sort(p) }
266
267
268
269
270 func Ints(a []int) { Sort(IntSlice(a)) }
271
272
273 func Float64s(a []float64) { Sort(Float64Slice(a)) }
274
275
276 func Strings(a []string) { Sort(StringSlice(a)) }
277
278
279 func IntsAreSorted(a []int) bool { return IsSorted(IntSlice(a)) }
280
281
282 func Float64sAreSorted(a []float64) bool { return IsSorted(Float64Slice(a)) }
283
284
285 func StringsAreSorted(a []string) bool { return IsSorted(StringSlice(a)) }
View as plain text