Skip to content

Commit 46cba63

Browse files
committed
add Odd-Even Merge Sort
1 parent 94bd99b commit 46cba63

File tree

10 files changed

+152
-31
lines changed

10 files changed

+152
-31
lines changed

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ Algorithms covered so far:
200200
| [Intro Sort (parallel)](#intro-sort) | ParallelIntroSort |
201201
| [Cycle Sort](#cycle-sort) | CycleSort |
202202
| [Odd-Even Sort](#odd-even-sort) | OddEvenSort |
203+
| [Odd-Even Merge Sort](#odd-even-merge-sort) | OddEvenMergeSort |
203204

204205

205206
<br />
@@ -560,4 +561,33 @@ In computing, an odd–even sort or odd–even transposition sort (also known as
560561

561562
| Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
562563
| :-: | :-: | :-: | :-: | :-: | :-: |
563-
| ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) |
564+
| ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) |
565+
566+
567+
568+
<br />
569+
<br />
570+
571+
## Odd-Even Merge Sort
572+
573+
<br />
574+
575+
odd–even mergesort is a generic construction devised by Ken Batcher for sorting networks of
576+
size
577+
<span> ![O(n(log_n)^2)](https://latex.codecogs.com/svg.image?O(n(\log&space;n)^2)) </span>
578+
and depth
579+
<span> ![O((log_n)^2)](https://latex.codecogs.com/svg.image?O((\log&space;n)^2)) </span>
580+
where n is the number of items to be sorted.
581+
582+
\[todo] add parallel-ver.
583+
584+
585+
<br />
586+
587+
### COMPLEXITY
588+
589+
590+
| Type | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
591+
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
592+
| non-parallel | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | yes | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) |
593+
| parallel | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | Yes | yes | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) |

glob_bench_test/sort_bench_test.go

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"github.com/kdgyun/GoSortingAlgorithms/sorts"
1212
)
1313

14+
var lengthforbench = 1 << 16
15+
1416
func sliceBuilder(len int) []int {
1517
seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
1618
rand.Seed(seed.Int64())
@@ -27,7 +29,7 @@ func sliceBuilder(len int) []int {
2729

2830
func BenchmarkBubbleSort(b *testing.B) {
2931
b.StopTimer()
30-
unsorted := sliceBuilder(100000)
32+
unsorted := sliceBuilder(lengthforbench)
3133
test := make([]int, len(unsorted))
3234

3335
for i := 0; i < b.N; i++ {
@@ -40,7 +42,7 @@ func BenchmarkBubbleSort(b *testing.B) {
4042

4143
func BenchmarkCocktailSort(b *testing.B) {
4244
b.StopTimer()
43-
unsorted := sliceBuilder(100000)
45+
unsorted := sliceBuilder(lengthforbench)
4446
test := make([]int, len(unsorted))
4547

4648
for i := 0; i < b.N; i++ {
@@ -53,7 +55,7 @@ func BenchmarkCocktailSort(b *testing.B) {
5355

5456
func BenchmarkInsertionSort(b *testing.B) {
5557
b.StopTimer()
56-
unsorted := sliceBuilder(100000)
58+
unsorted := sliceBuilder(lengthforbench)
5759
test := make([]int, len(unsorted))
5860

5961
for i := 0; i < b.N; i++ {
@@ -66,7 +68,7 @@ func BenchmarkInsertionSort(b *testing.B) {
6668

6769
func BenchmarkSelectionSort(b *testing.B) {
6870
b.StopTimer()
69-
unsorted := sliceBuilder(100000)
71+
unsorted := sliceBuilder(lengthforbench)
7072
test := make([]int, len(unsorted))
7173

7274
for i := 0; i < b.N; i++ {
@@ -79,7 +81,7 @@ func BenchmarkSelectionSort(b *testing.B) {
7981

8082
func BenchmarkShellSort(b *testing.B) {
8183
b.StopTimer()
82-
unsorted := sliceBuilder(100000)
84+
unsorted := sliceBuilder(lengthforbench)
8385
test := make([]int, len(unsorted))
8486

8587
for i := 0; i < b.N; i++ {
@@ -92,7 +94,7 @@ func BenchmarkShellSort(b *testing.B) {
9294

9395
func BenchmarkBottomUpMergeSort(b *testing.B) {
9496
b.StopTimer()
95-
unsorted := sliceBuilder(100000)
97+
unsorted := sliceBuilder(lengthforbench)
9698
test := make([]int, len(unsorted))
9799

98100
for i := 0; i < b.N; i++ {
@@ -105,7 +107,7 @@ func BenchmarkBottomUpMergeSort(b *testing.B) {
105107

106108
func BenchmarkTopDownMergeSort(b *testing.B) {
107109
b.StopTimer()
108-
unsorted := sliceBuilder(100000)
110+
unsorted := sliceBuilder(lengthforbench)
109111
test := make([]int, len(unsorted))
110112

111113
for i := 0; i < b.N; i++ {
@@ -118,7 +120,7 @@ func BenchmarkTopDownMergeSort(b *testing.B) {
118120

119121
func BenchmarkParallelMergeSort(b *testing.B) {
120122
b.StopTimer()
121-
unsorted := sliceBuilder(100000)
123+
unsorted := sliceBuilder(lengthforbench)
122124
test := make([]int, len(unsorted))
123125

124126
for i := 0; i < b.N; i++ {
@@ -131,7 +133,7 @@ func BenchmarkParallelMergeSort(b *testing.B) {
131133

132134
func BenchmarkHeapSort(b *testing.B) {
133135
b.StopTimer()
134-
unsorted := sliceBuilder(100000)
136+
unsorted := sliceBuilder(lengthforbench)
135137
test := make([]int, len(unsorted))
136138

137139
for i := 0; i < b.N; i++ {
@@ -144,7 +146,7 @@ func BenchmarkHeapSort(b *testing.B) {
144146

145147
func BenchmarkQuickSortLP(b *testing.B) {
146148
b.StopTimer()
147-
unsorted := sliceBuilder(100000)
149+
unsorted := sliceBuilder(lengthforbench)
148150
test := make([]int, len(unsorted))
149151

150152
for i := 0; i < b.N; i++ {
@@ -157,7 +159,7 @@ func BenchmarkQuickSortLP(b *testing.B) {
157159

158160
func BenchmarkQuickSort(b *testing.B) {
159161
b.StopTimer()
160-
unsorted := sliceBuilder(100000)
162+
unsorted := sliceBuilder(lengthforbench)
161163
test := make([]int, len(unsorted))
162164

163165
for i := 0; i < b.N; i++ {
@@ -170,7 +172,7 @@ func BenchmarkQuickSort(b *testing.B) {
170172

171173
func BenchmarkQuickSortRP(b *testing.B) {
172174
b.StopTimer()
173-
unsorted := sliceBuilder(100000)
175+
unsorted := sliceBuilder(lengthforbench)
174176
test := make([]int, len(unsorted))
175177

176178
for i := 0; i < b.N; i++ {
@@ -183,7 +185,7 @@ func BenchmarkQuickSortRP(b *testing.B) {
183185

184186
func BenchmarkParallelQuickSortLP(b *testing.B) {
185187
b.StopTimer()
186-
unsorted := sliceBuilder(100000)
188+
unsorted := sliceBuilder(lengthforbench)
187189
test := make([]int, len(unsorted))
188190

189191
for i := 0; i < b.N; i++ {
@@ -196,7 +198,7 @@ func BenchmarkParallelQuickSortLP(b *testing.B) {
196198

197199
func BenchmarkParallelQuickSort(b *testing.B) {
198200
b.StopTimer()
199-
unsorted := sliceBuilder(100000)
201+
unsorted := sliceBuilder(lengthforbench)
200202
test := make([]int, len(unsorted))
201203

202204
for i := 0; i < b.N; i++ {
@@ -209,7 +211,7 @@ func BenchmarkParallelQuickSort(b *testing.B) {
209211

210212
func BenchmarkParallelQuickSortRP(b *testing.B) {
211213
b.StopTimer()
212-
unsorted := sliceBuilder(100000)
214+
unsorted := sliceBuilder(lengthforbench)
213215
test := make([]int, len(unsorted))
214216

215217
for i := 0; i < b.N; i++ {
@@ -222,7 +224,7 @@ func BenchmarkParallelQuickSortRP(b *testing.B) {
222224

223225
func BenchmarkDualPivotQuickSort(b *testing.B) {
224226
b.StopTimer()
225-
unsorted := sliceBuilder(100000)
227+
unsorted := sliceBuilder(lengthforbench)
226228
test := make([]int, len(unsorted))
227229

228230
for i := 0; i < b.N; i++ {
@@ -235,7 +237,7 @@ func BenchmarkDualPivotQuickSort(b *testing.B) {
235237

236238
func BenchmarkParallelDualPivotQuickSort(b *testing.B) {
237239
b.StopTimer()
238-
unsorted := sliceBuilder(100000)
240+
unsorted := sliceBuilder(lengthforbench)
239241
test := make([]int, len(unsorted))
240242

241243
for i := 0; i < b.N; i++ {
@@ -248,7 +250,7 @@ func BenchmarkParallelDualPivotQuickSort(b *testing.B) {
248250

249251
func BenchmarkBinarySort(b *testing.B) {
250252
b.StopTimer()
251-
unsorted := sliceBuilder(100000)
253+
unsorted := sliceBuilder(lengthforbench)
252254
test := make([]int, len(unsorted))
253255

254256
for i := 0; i < b.N; i++ {
@@ -261,7 +263,7 @@ func BenchmarkBinarySort(b *testing.B) {
261263

262264
func BenchmarkTimSort(b *testing.B) {
263265
b.StopTimer()
264-
unsorted := sliceBuilder(100000)
266+
unsorted := sliceBuilder(lengthforbench)
265267
test := make([]int, len(unsorted))
266268

267269
for i := 0; i < b.N; i++ {
@@ -274,7 +276,7 @@ func BenchmarkTimSort(b *testing.B) {
274276

275277
func BenchmarkBitonicSort(b *testing.B) {
276278
b.StopTimer()
277-
unsorted := sliceBuilder(100000)
279+
unsorted := sliceBuilder(lengthforbench)
278280
test := make([]int, len(unsorted))
279281

280282
for i := 0; i < b.N; i++ {
@@ -287,7 +289,7 @@ func BenchmarkBitonicSort(b *testing.B) {
287289

288290
func BenchmarkParallelBitonicSort(b *testing.B) {
289291
b.StopTimer()
290-
unsorted := sliceBuilder(100000)
292+
unsorted := sliceBuilder(lengthforbench)
291293
test := make([]int, len(unsorted))
292294

293295
for i := 0; i < b.N; i++ {
@@ -300,7 +302,7 @@ func BenchmarkParallelBitonicSort(b *testing.B) {
300302

301303
func BenchmarkIntroSort(b *testing.B) {
302304
b.StopTimer()
303-
unsorted := sliceBuilder(100000)
305+
unsorted := sliceBuilder(lengthforbench)
304306
test := make([]int, len(unsorted))
305307

306308
for i := 0; i < b.N; i++ {
@@ -313,7 +315,7 @@ func BenchmarkIntroSort(b *testing.B) {
313315

314316
func BenchmarkParallelIntroSort(b *testing.B) {
315317
b.StopTimer()
316-
unsorted := sliceBuilder(100000)
318+
unsorted := sliceBuilder(lengthforbench)
317319
test := make([]int, len(unsorted))
318320

319321
for i := 0; i < b.N; i++ {
@@ -326,7 +328,7 @@ func BenchmarkParallelIntroSort(b *testing.B) {
326328

327329
func BenchmarkCycleSort(b *testing.B) {
328330
b.StopTimer()
329-
unsorted := sliceBuilder(100000)
331+
unsorted := sliceBuilder(lengthforbench)
330332
test := make([]int, len(unsorted))
331333

332334
for i := 0; i < b.N; i++ {
@@ -339,7 +341,7 @@ func BenchmarkCycleSort(b *testing.B) {
339341

340342
func BenchmarkOddEvenSort(b *testing.B) {
341343
b.StopTimer()
342-
unsorted := sliceBuilder(100000)
344+
unsorted := sliceBuilder(lengthforbench)
343345
test := make([]int, len(unsorted))
344346

345347
for i := 0; i < b.N; i++ {
@@ -349,3 +351,16 @@ func BenchmarkOddEvenSort(b *testing.B) {
349351
b.StopTimer()
350352
}
351353
}
354+
355+
func BenchmarkOddEvenMergeSort(b *testing.B) {
356+
b.StopTimer()
357+
unsorted := sliceBuilder(lengthforbench)
358+
test := make([]int, len(unsorted))
359+
360+
for i := 0; i < b.N; i++ {
361+
copy(test, unsorted)
362+
b.StartTimer()
363+
sorts.OddEvenMergeSort(test)
364+
b.StopTimer()
365+
}
366+
}

glob_bench_test/sort_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,14 @@ func TestSort(t *testing.T) {
212212
if !reflect.DeepEqual(test, verify) {
213213
t.Error("Wrong result [odd-even sort]")
214214
}
215-
size *= 10
215+
216+
test = make([]int, len(origin))
217+
copy(test, origin)
218+
t.Run("odd-even merge sort", func(t *testing.T) { sorts.OddEvenMergeSort(test) })
219+
220+
if !reflect.DeepEqual(test, verify) {
221+
t.Error("Wrong result [odd-even sort]")
222+
}
223+
size <<= 2
216224
}
217225
}

go.mod

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/kdgyun/GoSortingAlgorithms
22

3-
go 1.17
3+
go 1.17
4+
5+
require github.com/logrusorgru/aurora/v3 v3.0.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/logrusorgru/aurora/v3 v3.0.0 h1:R6zcoZZbvVcGMvDCKo45A9U/lzYyzl5NfYIvznmDfE4=
2+
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=

simplytest/base_sort_list.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/kdgyun/GoSortingAlgorithms/sorts"
15+
"github.com/logrusorgru/aurora/v3"
1516
)
1617

1718
func CallBubbleSort(origin []int, verify []int, callName string) OutputForm {
@@ -363,3 +364,23 @@ func CallOddEvenSort(origin []int, verify []int, callName string) OutputForm {
363364
}
364365
return OutputForm{false, callName, -1, false, ""}
365366
}
367+
368+
func CallOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
369+
size := len(origin)
370+
if (size & (size - 1)) != 0 {
371+
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("top-down odd-even sort can't run"))
372+
fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
373+
return OutputForm{false, callName, -1, false, ""}
374+
}
375+
if ODDEVEN_MERGE_SORT {
376+
test := make([]int, len(origin))
377+
copy(test, origin)
378+
fmt.Printf("runing %s...\n", callName)
379+
start := time.Now()
380+
sorts.OddEvenMergeSort(test)
381+
end := time.Since(start)
382+
eq, err := Equal(verify, test)
383+
return OutputForm{true, callName, end.Nanoseconds(), eq, err}
384+
}
385+
return OutputForm{false, callName, -1, false, ""}
386+
}

simplytest/compare.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func Equal(verify, b []int) (bool, string) {
1616
}
1717
for i, v := range verify {
1818
if v != b[i] {
19-
s := fmt.Sprintf("\t1st diff : elements\tstart idx %d [...(correct v : %d, incorrect v : %d) ...]",
19+
s := fmt.Sprintf("\t1elements not sorted",
2020
i, verify[i], b[i])
2121
fmt.Errorf(s)
2222
return false, s

simplytest/option.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const (
3737
PARALLEL_INTRO_SORT Activate = true
3838
CYCLE_SORT Activate = true
3939
ODDEVEN_SORT Activate = true
40+
ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
4041
)
4142

4243
// Section 2.
@@ -49,4 +50,4 @@ const (
4950

5051
// Section 3.
5152
// lengths for test
52-
var lengths = [...]int{10, 100, 1000, 10000, 100000}
53+
var lengths = [...]int{1 << 4, 1 << 7, 1 << 10, 1 << 13, 1 << 16}

simplytest/test_run.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"fmt"
1212
"strings"
1313
"time"
14+
15+
"github.com/logrusorgru/aurora/v3"
1416
)
1517

1618
type OutputForm struct {
@@ -50,10 +52,11 @@ func callSortTest(origin, verify []int) {
5052
q = append(q, CallParallelIntroSort(origin, verify, "parallel intro sort"))
5153
q = append(q, CallCycleSort(origin, verify, "cycle sort"))
5254
q = append(q, CallOddEvenSort(origin, verify, "odd-even sort"))
55+
q = append(q, CallOddEvenMergeSort(origin, verify, "odd-even merge sort"))
5356
var pf string = ""
5457

5558
pf += fmt.Sprintf("\n+%s+\n", strings.Repeat("-", 97))
56-
pf += fmt.Sprintf("| %35s | %23s | %18s | %10s | \t (err mag) \n", "name", "ns", "ms", "verify")
59+
pf += fmt.Sprintf("| %35s | %23s | %18s | %10s | \t %s \n", "name", "ns", "ms", "verify", aurora.BrightRed("(err mag)"))
5760

5861
for _, v := range q {
5962
if v.active {

0 commit comments

Comments
 (0)