Skip to content

Commit

Permalink
add Odd-Even Merge Sort
Browse files Browse the repository at this point in the history
  • Loading branch information
kdgyun committed Feb 23, 2022
1 parent 94bd99b commit 46cba63
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 31 deletions.
32 changes: 31 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ Algorithms covered so far:
| [Intro Sort (parallel)](#intro-sort) | ParallelIntroSort |
| [Cycle Sort](#cycle-sort) | CycleSort |
| [Odd-Even Sort](#odd-even-sort) | OddEvenSort |
| [Odd-Even Merge Sort](#odd-even-merge-sort) | OddEvenMergeSort |


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

| Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
| :-: | :-: | :-: | :-: | :-: | :-: |
| ![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)) |
| ![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)) |



<br />
<br />

## Odd-Even Merge Sort

<br />

odd–even mergesort is a generic construction devised by Ken Batcher for sorting networks of
size
<span> ![O(n(log_n)^2)](https://latex.codecogs.com/svg.image?O(n(\log&space;n)^2)) </span>
and depth
<span> ![O((log_n)^2)](https://latex.codecogs.com/svg.image?O((\log&space;n)^2)) </span>
where n is the number of items to be sorted.

\[todo] add parallel-ver.


<br />

### COMPLEXITY


| Type | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| 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)) |
| 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)) |
65 changes: 40 additions & 25 deletions glob_bench_test/sort_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"github.com/kdgyun/GoSortingAlgorithms/sorts"
)

var lengthforbench = 1 << 16

func sliceBuilder(len int) []int {
seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
rand.Seed(seed.Int64())
Expand All @@ -27,7 +29,7 @@ func sliceBuilder(len int) []int {

func BenchmarkBubbleSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkCocktailSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkInsertionSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkSelectionSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkShellSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkBottomUpMergeSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkTopDownMergeSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelMergeSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkHeapSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkQuickSortLP(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkQuickSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkQuickSortRP(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelQuickSortLP(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelQuickSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelQuickSortRP(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkDualPivotQuickSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelDualPivotQuickSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkBinarySort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkTimSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkBitonicSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelBitonicSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkIntroSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkParallelIntroSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkCycleSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

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

func BenchmarkOddEvenSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(100000)
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

for i := 0; i < b.N; i++ {
Expand All @@ -349,3 +351,16 @@ func BenchmarkOddEvenSort(b *testing.B) {
b.StopTimer()
}
}

func BenchmarkOddEvenMergeSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

for i := 0; i < b.N; i++ {
copy(test, unsorted)
b.StartTimer()
sorts.OddEvenMergeSort(test)
b.StopTimer()
}
}
10 changes: 9 additions & 1 deletion glob_bench_test/sort_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ func TestSort(t *testing.T) {
if !reflect.DeepEqual(test, verify) {
t.Error("Wrong result [odd-even sort]")
}
size *= 10

test = make([]int, len(origin))
copy(test, origin)
t.Run("odd-even merge sort", func(t *testing.T) { sorts.OddEvenMergeSort(test) })

if !reflect.DeepEqual(test, verify) {
t.Error("Wrong result [odd-even sort]")
}
size <<= 2
}
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
module github.com/kdgyun/GoSortingAlgorithms

go 1.17
go 1.17

require github.com/logrusorgru/aurora/v3 v3.0.0 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/logrusorgru/aurora/v3 v3.0.0 h1:R6zcoZZbvVcGMvDCKo45A9U/lzYyzl5NfYIvznmDfE4=
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
21 changes: 21 additions & 0 deletions simplytest/base_sort_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/kdgyun/GoSortingAlgorithms/sorts"
"github.com/logrusorgru/aurora/v3"
)

func CallBubbleSort(origin []int, verify []int, callName string) OutputForm {
Expand Down Expand Up @@ -363,3 +364,23 @@ func CallOddEvenSort(origin []int, verify []int, callName string) OutputForm {
}
return OutputForm{false, callName, -1, false, ""}
}

func CallOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
size := len(origin)
if (size & (size - 1)) != 0 {
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("top-down odd-even sort can't run"))
fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
return OutputForm{false, callName, -1, false, ""}
}
if ODDEVEN_MERGE_SORT {
test := make([]int, len(origin))
copy(test, origin)
fmt.Printf("runing %s...\n", callName)
start := time.Now()
sorts.OddEvenMergeSort(test)
end := time.Since(start)
eq, err := Equal(verify, test)
return OutputForm{true, callName, end.Nanoseconds(), eq, err}
}
return OutputForm{false, callName, -1, false, ""}
}
2 changes: 1 addition & 1 deletion simplytest/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func Equal(verify, b []int) (bool, string) {
}
for i, v := range verify {
if v != b[i] {
s := fmt.Sprintf("\t1st diff : elements\tstart idx %d [...(correct v : %d, incorrect v : %d) ...]",
s := fmt.Sprintf("\t1elements not sorted",
i, verify[i], b[i])
fmt.Errorf(s)
return false, s
Expand Down
3 changes: 2 additions & 1 deletion simplytest/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const (
PARALLEL_INTRO_SORT Activate = true
CYCLE_SORT Activate = true
ODDEVEN_SORT Activate = true
ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
)

// Section 2.
Expand All @@ -49,4 +50,4 @@ const (

// Section 3.
// lengths for test
var lengths = [...]int{10, 100, 1000, 10000, 100000}
var lengths = [...]int{1 << 4, 1 << 7, 1 << 10, 1 << 13, 1 << 16}
5 changes: 4 additions & 1 deletion simplytest/test_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"fmt"
"strings"
"time"

"github.com/logrusorgru/aurora/v3"
)

type OutputForm struct {
Expand Down Expand Up @@ -50,10 +52,11 @@ func callSortTest(origin, verify []int) {
q = append(q, CallParallelIntroSort(origin, verify, "parallel intro sort"))
q = append(q, CallCycleSort(origin, verify, "cycle sort"))
q = append(q, CallOddEvenSort(origin, verify, "odd-even sort"))
q = append(q, CallOddEvenMergeSort(origin, verify, "odd-even merge sort"))
var pf string = ""

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

for _, v := range q {
if v.active {
Expand Down
Loading

0 comments on commit 46cba63

Please sign in to comment.