├── go.mod
├── go.sum
├── simplytest
├── runner.go
├── compare.go
├── test_random.go
├── test_ascending.go
├── test_descending.go
├── slice_builder.go
├── option.go
├── test_run.go
└── base_sort_list.go
├── sorts
├── insertion_sort.go
├── selection_sort.go
├── odd_even_sort.go
├── bubble_sort.go
├── comb_sort.go
├── cycle_sort.go
├── cocktail_sort.go
├── quick_sort_of_left_pivot.go
├── quick_sort_of_middle_pivot.go
├── quick_sort_of_right_pivot.go
├── odd_even_merge_sort.go
├── bitonic_sort.go
├── heap_sort.go
├── dual_pivot_quick_sort.go
├── top_down_merge_sort.go
├── shell_sort.go
├── bottom_up_merge_sort.go
├── binary_insertion_sort.go
├── parallel_quick_sort_of_left_pivot.go
├── parallel_quick_sort_of_middle_pivot.go
├── parallel_quick_sort_of_right_pivot.go
├── parallel_merge_sort.go
├── parallel_dual_pivot_quick_sort.go
├── intro_sort.go
├── parallel_odd_even_merge_sort.go
├── parallel_bitonic_sort.go
├── parallel_intro_sort.go
└── tim_sort.go
├── .github
└── workflows
│ └── go.yml
├── .gitignore
├── glob_bench_test
├── sort_test.go
└── sort_bench_test.go
├── LICENSE
├── README.md
└── README-en.md
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/kdgyun/GoSortingAlgorithms
2 |
3 | go 1.17
4 |
5 | require github.com/logrusorgru/aurora/v3 v3.0.0 // indirect
6 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
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=
3 |
--------------------------------------------------------------------------------
/simplytest/runner.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | func RunTest() {
11 | if ASCENDING_TEST {
12 | AscendingTest()
13 | }
14 | if DESCENDING_TEST {
15 | DescendingTest()
16 | }
17 | if RANDOM_TEST {
18 | RandomTest()
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/sorts/insertion_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func InsertionSort(a []int) {
11 | insertionSort(a, 0, len(a))
12 | }
13 |
14 | func insertionSort(a []int, lo, hi int) {
15 |
16 | for i := lo + 1; i < hi; i++ {
17 | target := a[i]
18 | j := i - 1
19 |
20 | for j >= lo && target < a[j] {
21 | a[j+1] = a[j]
22 | j--
23 | }
24 |
25 | a[j+1] = target
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/sorts/selection_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func SelectionSort(a []int) {
11 | selectionSort(a, 0, len(a))
12 | }
13 |
14 | func selectionSort(a []int, lo, hi int) {
15 | for i := lo; i < hi-1; i++ {
16 | minIdx := i
17 |
18 | for j := i + 1; j < hi; j++ {
19 | if a[j] < a[minIdx] {
20 | minIdx = j
21 | }
22 | }
23 | a[minIdx], a[i] = a[i], a[minIdx]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/sorts/odd_even_sort.go:
--------------------------------------------------------------------------------
1 | package sorts
2 |
3 | func OddEvenSort(a []int) {
4 | oddEvenSort(a, 0, len(a))
5 | }
6 |
7 | func oddEvenSort(a []int, lo, hi int) {
8 | sorted := false
9 | for !sorted {
10 | sorted = true
11 |
12 | for i := lo; i < hi-1; i += 2 {
13 | if a[i] > a[i+1] {
14 | a[i], a[i+1] = a[i+1], a[i]
15 | sorted = false
16 | }
17 | }
18 |
19 | for i := lo + 1; i < hi-1; i += 2 {
20 | if a[i] > a[i+1] {
21 | a[i], a[i+1] = a[i+1], a[i]
22 | sorted = false
23 | }
24 | }
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/simplytest/compare.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import "fmt"
11 |
12 | func Equal(verify, b []int) (bool, string) {
13 | if len(verify) != len(b) {
14 | fmt.Errorf("\tdiff : length\t")
15 | return false, "\tdiff : length\t"
16 | }
17 | for i, v := range verify {
18 | if v != b[i] {
19 | s := fmt.Sprintf("\t1elements not sorted",
20 | i, verify[i], b[i])
21 | fmt.Errorf(s)
22 | return false, s
23 | }
24 | }
25 | return true, ""
26 | }
27 |
--------------------------------------------------------------------------------
/simplytest/test_random.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import (
11 | "fmt"
12 | "strings"
13 | )
14 |
15 | func RandomTest() {
16 | fmt.Printf("\n+%s+\n", strings.Repeat("=", 82))
17 | fmt.Printf("|%46s%36s|\n", "Random Test", " ")
18 | fmt.Printf("+%s+\n\n\n", strings.Repeat("=", 82))
19 | for _, v := range lengths {
20 | runRandom(v)
21 | }
22 | }
23 | func runRandom(len int) {
24 | origin, verify := RANDOM_INT(len)
25 | callSortTest(origin, verify)
26 | }
27 |
--------------------------------------------------------------------------------
/simplytest/test_ascending.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import (
11 | "fmt"
12 | "strings"
13 | )
14 |
15 | func AscendingTest() {
16 | fmt.Printf("\n+%s+\n", strings.Repeat("=", 82))
17 | fmt.Printf("|%48s%34s|\n", "Ascending Test", " ")
18 | fmt.Printf("+%s+\n\n\n", strings.Repeat("=", 82))
19 | for _, v := range lengths {
20 | runAscending(v)
21 | }
22 | }
23 |
24 | func runAscending(len int) {
25 | origin, verify := ASCENDING_INT(len)
26 |
27 | callSortTest(origin, verify)
28 | }
29 |
--------------------------------------------------------------------------------
/sorts/bubble_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func BubbleSort(a []int) {
11 | bubbleSort(a, 0, len(a))
12 | }
13 |
14 | func bubbleSort(a []int, lo, hi int) {
15 |
16 | for i := lo + 1; i < hi; i++ {
17 | var swapped bool = false
18 |
19 | for j := lo; j < hi-i; j++ {
20 | if a[j] > a[j+1] {
21 | a[j], a[j+1] = a[j+1], a[j] // swap
22 | swapped = true
23 | }
24 | }
25 | if !swapped { // [optimizing] if array is ordered, exit this method .
26 | break
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/simplytest/test_descending.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import (
11 | "fmt"
12 | "strings"
13 | )
14 |
15 | func DescendingTest() {
16 | fmt.Printf("\n+%s+\n", strings.Repeat("=", 82))
17 | fmt.Printf("|%49s%33s|\n", "Descending Test", " ")
18 | fmt.Printf("+%s+\n\n\n", strings.Repeat("=", 82))
19 | for _, v := range lengths {
20 | runDescending(v)
21 | }
22 | }
23 | func runDescending(len int) {
24 |
25 | origin, verify := DESCENDING_INT(len)
26 |
27 | callSortTest(origin, verify)
28 | }
29 |
--------------------------------------------------------------------------------
/sorts/comb_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func CombSort(a []int) {
11 | combSort(a, 0, len(a))
12 | }
13 |
14 | func combSort(a []int, lo, hi int) {
15 | gap := hi - lo
16 | shrink := 1.3
17 | sorted := false
18 |
19 | for !sorted {
20 | gap = int(float64(gap) / (shrink))
21 | if gap <= 1 {
22 | sorted = true
23 | gap = 1
24 | }
25 |
26 | for i := lo; i < hi-gap; i++ {
27 | if a[i] > a[i+gap] {
28 | a[i], a[i+gap] = a[i+gap], a[i]
29 | sorted = false
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Go
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 |
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v2
15 |
16 | - name: Set up Go
17 | uses: actions/setup-go@v2
18 | with:
19 | go-version: 1.17
20 |
21 | - name: Build
22 | run: go build -v ./...
23 |
24 | - name: Test
25 | run: go test -timeout 20m -v ./glob_bench_test/sort_test.go
26 |
27 | - name: Benchmark
28 | run: go test -timeout 20m -bench=. -cpu 1,2,4,8,16,32 -benchmem -v ./glob_bench_test/sort_bench_test.go
29 |
--------------------------------------------------------------------------------
/sorts/cycle_sort.go:
--------------------------------------------------------------------------------
1 | package sorts
2 |
3 | func CycleSort(a []int) {
4 | cycleSort(a, 0, len(a))
5 | }
6 |
7 | func cycleSort(a []int, left, right int) {
8 |
9 | for start := left; start < right; start++ {
10 | item := a[start]
11 | pos := start
12 |
13 | for i := start + 1; i < right; i++ {
14 | if a[i] < item {
15 | pos++
16 | }
17 | }
18 |
19 | if pos == start {
20 | continue
21 | }
22 |
23 | for item == a[pos] {
24 | pos++
25 | }
26 |
27 | a[pos], item = item, a[pos]
28 |
29 | for pos != start {
30 | pos = start
31 | for i := start + 1; i < right; i++ {
32 | if a[i] < item {
33 | pos++
34 | }
35 | }
36 |
37 | for item == a[pos] {
38 | pos++
39 | }
40 | a[pos], item = item, a[pos]
41 |
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/sorts/cocktail_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func CocktailSort(a []int) {
11 | cocktailSort(a, 0, len(a))
12 | }
13 |
14 | func cocktailSort(a []int, left, right int) {
15 | lo := left
16 | hi := right
17 | var swapped bool = true
18 |
19 | for swapped {
20 | swapped = false
21 |
22 | for i := lo; i < hi-1; i++ {
23 | if a[i] > a[i+1] {
24 | a[i], a[i+1] = a[i+1], a[i]
25 | swapped = true
26 | }
27 | }
28 |
29 | if !swapped {
30 | break
31 | }
32 |
33 | swapped = false
34 |
35 | hi--
36 | for i := hi - 1; i >= lo; i-- {
37 | if a[i] > a[i+1] {
38 | a[i], a[i+1] = a[i+1], a[i]
39 | swapped = true
40 | }
41 | }
42 | lo++
43 |
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/sorts/quick_sort_of_left_pivot.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | // This Quick sort is implemented with left element selected as the pivot
9 |
10 | package sorts
11 |
12 | func QuickSortLP(a []int) {
13 | quickSortLP(a, 0, len(a))
14 | }
15 |
16 | func quickSortLP(a []int, lo, hi int) {
17 |
18 | if hi-lo < 2 {
19 | return
20 | }
21 | pivot := partitionLP(a, lo, hi-1)
22 | quickSortLP(a, lo, pivot)
23 | quickSortLP(a, pivot+1, hi)
24 | }
25 |
26 | func partitionLP(a []int, left, right int) int {
27 | lo := left
28 | hi := right
29 | pivot := a[left]
30 |
31 | for lo < hi {
32 | for a[hi] > pivot {
33 | hi--
34 | }
35 | for a[lo] <= pivot && lo < hi {
36 | lo++
37 | }
38 |
39 | a[lo], a[hi] = a[hi], a[lo]
40 | }
41 | a[left], a[lo] = a[lo], a[left]
42 | return lo
43 | }
44 |
--------------------------------------------------------------------------------
/sorts/quick_sort_of_middle_pivot.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | // This Quick sort is implemented with middle element selected as the pivot
9 |
10 | package sorts
11 |
12 | func QuickSort(a []int) {
13 | quickSort(a, 0, len(a))
14 | }
15 |
16 | func quickSort(a []int, lo, hi int) {
17 |
18 | if hi-lo < 2 {
19 | return
20 | }
21 | pivot := partition(a, lo, hi-1)
22 | quickSort(a, lo, pivot)
23 | quickSort(a, pivot+1, hi)
24 | }
25 |
26 | func partition(a []int, left, right int) int {
27 | lo := left
28 | hi := right
29 | pivot := a[(left+right)>>1]
30 |
31 | for true {
32 | for a[lo] < pivot {
33 | lo++
34 | }
35 | for a[hi] > pivot && lo <= hi {
36 | hi--
37 | }
38 | if lo >= hi {
39 | return hi
40 | }
41 |
42 | a[lo], a[hi] = a[hi], a[lo]
43 | }
44 | return hi
45 | }
46 |
--------------------------------------------------------------------------------
/sorts/quick_sort_of_right_pivot.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | // This Quick sort is implemented with right element selected as the pivot
9 |
10 | package sorts
11 |
12 | func QuickSortRP(a []int) {
13 | quickSortLP(a, 0, len(a))
14 | }
15 |
16 | func quickSortRP(a []int, lo, hi int) {
17 |
18 | if hi-lo < 2 {
19 | return
20 | }
21 | pivot := partitionRP(a, lo, hi-1)
22 | quickSortRP(a, lo, pivot)
23 | quickSortRP(a, pivot+1, hi)
24 | }
25 |
26 | func partitionRP(a []int, left, right int) int {
27 | lo := left
28 | hi := right
29 | pivot := a[right]
30 |
31 | for lo < hi {
32 | for a[lo] < pivot && lo < hi {
33 | lo++
34 | }
35 | for a[hi] >= pivot && lo < hi {
36 | hi--
37 | }
38 |
39 | a[lo], a[hi] = a[hi], a[lo]
40 | }
41 | a[right], a[hi] = a[hi], a[right]
42 | return lo
43 | }
44 |
--------------------------------------------------------------------------------
/sorts/odd_even_merge_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func OddEvenMergeSort(a []int) {
11 | oddEvenMergeSort(a, 0, len(a))
12 | }
13 |
14 | func oddEvenMergeSort(a []int, lo, hi int) {
15 | if hi-lo > 1 {
16 | mid := (hi + lo) >> 1
17 | oddEvenMergeSort(a, lo, mid)
18 | oddEvenMergeSort(a, mid, hi)
19 | oddEvenMerge(a, lo, hi, 1)
20 | }
21 | }
22 |
23 | func oddEvenMerge(a []int, lo, hi, dist int) {
24 | subDist := dist << 1
25 | if subDist < (hi - lo) {
26 | oddEvenMerge(a, lo, hi, subDist)
27 | oddEvenMerge(a, lo+dist, hi, subDist)
28 | for i := lo + dist; i+dist < hi; i += subDist {
29 |
30 | if a[i] > a[i+dist] {
31 | a[i], a[i+dist] = a[i+dist], a[i]
32 | }
33 | }
34 | } else {
35 | if a[lo] > a[lo+dist] {
36 | a[lo], a[lo+dist] = a[lo+dist], a[lo]
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/sorts/bitonic_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func bitonicMerge(a []int, lo, len int, dir bool) {
11 | if len > 1 {
12 | m := greatestPowerOfTwoLessThan(len)
13 |
14 | for i := lo; i < lo+len-m; i++ {
15 | if dir == (a[i] > a[i+m]) {
16 | a[i], a[i+m] = a[i+m], a[i]
17 | }
18 | }
19 | bitonicMerge(a, lo, m, dir)
20 | bitonicMerge(a, lo+m, len-m, dir)
21 | }
22 |
23 | }
24 |
25 | func BitonicSort(a []int) {
26 | bitonicSort(a, 0, len(a), true)
27 | }
28 |
29 | func bitonicSort(a []int, lo, len int, dir bool) {
30 |
31 | if len > 1 {
32 | mid := len >> 1
33 | bitonicSort(a, lo, mid, !dir)
34 | bitonicSort(a, lo+mid, len-mid, dir)
35 | bitonicMerge(a, lo, len, dir)
36 | }
37 | }
38 |
39 | func greatestPowerOfTwoLessThan(n int) int {
40 | k := 1
41 | for k > 0 && k < n {
42 | k <<= 1
43 | }
44 | return k >> 1
45 | }
46 |
--------------------------------------------------------------------------------
/sorts/heap_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func HeapSort(a []int) {
11 | heapSort(a, 0, len(a))
12 | }
13 |
14 | func heapSort(a []int, lo, hi int) {
15 |
16 | if hi-lo < 2 {
17 | return
18 | }
19 | last := hi - 1
20 | parent := ((last - 1) >> 1)
21 |
22 | for parent >= lo {
23 | heapify(a, parent, last)
24 | parent--
25 | }
26 |
27 | end := hi - 1
28 | for end > lo {
29 | a[lo], a[end] = a[end], a[lo]
30 | end--
31 | heapify(a, lo, end)
32 | }
33 | }
34 |
35 | func heapify(a []int, cur, last int) {
36 | var left, right, large int
37 |
38 | for ((cur << 1) + 1) <= last {
39 | left = (cur << 1) + 1
40 | right = (cur << 1) + 2
41 | large = cur
42 |
43 | if a[left] > a[large] {
44 | large = left
45 | }
46 |
47 | if right <= last && a[right] > a[large] {
48 | large = right
49 | }
50 |
51 | if large != cur {
52 | a[cur], a[large] = a[large], a[cur]
53 | cur = large
54 | } else {
55 | return
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/sorts/dual_pivot_quick_sort.go:
--------------------------------------------------------------------------------
1 | package sorts
2 |
3 | func DualPivotQuickSort(a []int) {
4 | dualPivotQuickSort(a, 0, len(a))
5 |
6 | }
7 |
8 | func dualPivotQuickSort(a []int, lo, hi int) {
9 |
10 | if hi-lo < 2 {
11 | return
12 | }
13 |
14 | lp, rp := _3wayQuickPartition(a, lo, hi-1)
15 | dualPivotQuickSort(a, lo, lp)
16 | dualPivotQuickSort(a, lp+1, rp)
17 | dualPivotQuickSort(a, rp+1, hi)
18 |
19 | }
20 |
21 | func _3wayQuickPartition(a []int, lo, hi int) (int, int) {
22 |
23 | if a[lo] > a[hi] {
24 | a[lo], a[hi] = a[hi], a[lo]
25 | }
26 |
27 | l := lo + 1
28 | k := lo + 1
29 | g := hi - 1
30 |
31 | leftPivot := a[lo]
32 | rightPivot := a[hi]
33 |
34 | for k <= g {
35 | if a[k] < leftPivot {
36 | a[k], a[l] = a[l], a[k]
37 | l++
38 | } else if a[k] >= rightPivot {
39 | for rightPivot < a[g] && k < g {
40 | g--
41 | }
42 | a[k], a[g] = a[g], a[k]
43 | g--
44 |
45 | if a[k] < leftPivot {
46 | a[k], a[l] = a[l], a[k]
47 | l++
48 | }
49 | }
50 | k++
51 | }
52 | l--
53 | g++
54 |
55 | a[lo], a[l] = a[l], a[lo]
56 | a[hi], a[g] = a[g], a[hi]
57 |
58 | return l, g
59 | }
60 |
--------------------------------------------------------------------------------
/sorts/top_down_merge_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func TopDownMergeSort(a []int) {
11 | temp := make([]int, len(a))
12 | topDownMergeSort(a, temp, 0, len(a))
13 | }
14 |
15 | func topDownMergeSort(a, temp []int, left int, right int) {
16 |
17 | if right-left < 2 {
18 | return
19 | }
20 | mid := (left + right) / 2
21 | topDownMergeSort(a, temp, left, mid)
22 | topDownMergeSort(a, temp, mid, right)
23 | mergeForTopDown(a, temp, left, mid, right)
24 | }
25 |
26 | func mergeForTopDown(origin, temp []int, left, mid, right int) {
27 | l := left
28 | r := mid
29 | idx := left
30 | for l < mid && r < right {
31 | if origin[l] <= origin[r] {
32 | temp[idx] = origin[l]
33 | idx++
34 | l++
35 | } else {
36 | temp[idx] = origin[r]
37 | idx++
38 | r++
39 | }
40 | }
41 | if l == mid {
42 | for r < right {
43 | temp[idx] = origin[r]
44 | idx++
45 | r++
46 | }
47 | } else {
48 | for l < mid {
49 | temp[idx] = origin[l]
50 | idx++
51 | l++
52 | }
53 | }
54 |
55 | copy(origin[left:], temp[left:right])
56 | }
57 |
--------------------------------------------------------------------------------
/sorts/shell_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | /*
11 | Gap sequence is based on the Ciura sequence.
12 | The number after 1750 is obtained by multiplying by 2.25.
13 | link : https://en.wikipedia.org/wiki/Shellsort#Gap_sequences
14 | */
15 | var Gap = [...]int{1, 4, 10, 23, 57, 132, 301, 701, 1750, 3937, 8858, 19930, 44842, 100894, 227011, 510774, 1149241, 2585792, 5818032, 13090572, 29453787, 66271020, 149109795, 335497038, 754868335, 1698453753}
16 |
17 | func getGap(len int) int {
18 | idx := 0
19 | threshold := int(float32(len) / 2.25)
20 |
21 | for Gap[idx] < threshold {
22 | idx++
23 | }
24 | return idx
25 | }
26 |
27 | func ShellSort(a []int) {
28 | shellSort(a, 0, len(a), len(a))
29 | }
30 |
31 | func shellSort(a []int, lo, hi, len int) {
32 |
33 | pos := getGap(hi - lo)
34 |
35 | for pos >= 0 {
36 | step := Gap[pos]
37 | pos--
38 |
39 | for i := step + lo; i < hi; i++ {
40 | target := a[i]
41 | j := i
42 |
43 | for ; j >= step+lo && target < a[j-step]; j -= step {
44 | a[j] = a[j-step]
45 | }
46 | a[j] = target
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/sorts/bottom_up_merge_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | func BottomUpMergeSort(a []int) {
11 | bottomUpMergeSort(a, 0, len(a))
12 | }
13 |
14 | func bottomUpMergeSort(a []int, left int, right int) {
15 | temp := make([]int, right)
16 | for size := 1; size < right; size += size {
17 |
18 | for l := left; l < right-size; l += (2 * size) {
19 | var high int
20 | mid := l + size
21 |
22 | if l+(2*size) < right {
23 | high = l + (2 * size)
24 | } else {
25 | high = right
26 | }
27 |
28 | mergeForBottomUp(a, temp, l, mid, high)
29 | }
30 | }
31 | }
32 |
33 | func mergeForBottomUp(origin, temp []int, left, mid, right int) {
34 | l := left
35 | r := mid
36 | idx := left
37 | for l < mid && r < right {
38 | if origin[l] <= origin[r] {
39 | temp[idx] = origin[l]
40 | idx++
41 | l++
42 | } else {
43 | temp[idx] = origin[r]
44 | idx++
45 | r++
46 | }
47 | }
48 | if l == mid {
49 | for r < right {
50 | temp[idx] = origin[r]
51 | idx++
52 | r++
53 | }
54 | } else {
55 | for l < mid {
56 | temp[idx] = origin[l]
57 | idx++
58 | l++
59 | }
60 | }
61 |
62 | copy(origin[left:], temp[left:right])
63 | }
64 |
--------------------------------------------------------------------------------
/sorts/binary_insertion_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 | package sorts
8 |
9 | func getAscending(a []int, lo, hi int) int {
10 | limit := lo + 1
11 | if limit == hi {
12 | return 1
13 | }
14 |
15 | if a[lo] <= a[limit] {
16 | for limit < hi && a[limit-1] <= a[limit] {
17 | limit++
18 | }
19 | } else {
20 | for limit < hi && a[limit-1] > a[limit] {
21 | limit++
22 | }
23 | reversing(a, lo, limit)
24 | }
25 | return limit - lo
26 | }
27 |
28 | func reversing(a []int, lo, hi int) {
29 | hi--
30 | for lo < hi {
31 | a[lo], a[hi] = a[hi], a[lo]
32 | lo++
33 | hi--
34 | }
35 | }
36 |
37 | func BinarySort(a []int) {
38 | if len(a) < 2 {
39 | return
40 | }
41 | incLength := getAscending(a, 0, len(a))
42 | binarySort(a, 0, len(a), incLength)
43 | }
44 |
45 | func binarySort(a []int, lo, hi, start int) {
46 |
47 | if lo == start {
48 | start++
49 | }
50 |
51 | for ; start < hi; start++ {
52 | target := a[start]
53 |
54 | locate := binarySearch(a, target, lo, start)
55 | j := start - 1
56 |
57 | for j >= locate {
58 | a[j+1] = a[j]
59 | j--
60 | }
61 | a[locate] = target
62 | }
63 | }
64 |
65 | func binarySearch(a []int, key, lo, hi int) int {
66 |
67 | for lo < hi {
68 | mid := lo + ((hi - lo) >> 1)
69 |
70 | if key < a[mid] {
71 | hi = mid
72 | } else {
73 | lo = mid + 1
74 | }
75 |
76 | }
77 | return lo
78 | }
79 |
--------------------------------------------------------------------------------
/sorts/parallel_quick_sort_of_left_pivot.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | // This Parallel Quick sort is implemented with left element selected as the pivot
9 |
10 | package sorts
11 |
12 | import (
13 | "runtime"
14 | "sync"
15 | )
16 |
17 | func ParallelQuickSortLP(a []int) {
18 | runtime.GOMAXPROCS(runtime.NumCPU())
19 | parallelQuickSortLP(a, 0, len(a))
20 | }
21 |
22 | func parallelQuickSortLP(a []int, lo, hi int) {
23 |
24 | if hi-lo < 2 {
25 | return
26 | }
27 |
28 | // 2048 is threshold
29 | if hi-lo > 2048 {
30 | pivot := parallelPartitionLP(a, lo, hi-1)
31 |
32 | var wg sync.WaitGroup
33 | wg.Add(1)
34 | go func() {
35 | defer wg.Done()
36 | parallelQuickSortLP(a, lo, pivot)
37 | }()
38 | parallelQuickSortLP(a, pivot+1, hi)
39 | wg.Wait()
40 | } else {
41 | basicQuickSortLP(a, lo, hi)
42 | }
43 | }
44 |
45 | func parallelPartitionLP(a []int, left, right int) int {
46 | lo := left
47 | hi := right
48 | pivot := a[left]
49 |
50 | for lo < hi {
51 | for a[hi] > pivot {
52 | hi--
53 | }
54 | for a[lo] <= pivot && lo < hi {
55 | lo++
56 | }
57 |
58 | a[lo], a[hi] = a[hi], a[lo]
59 | }
60 | a[left], a[lo] = a[lo], a[left]
61 | return lo
62 | }
63 |
64 | func basicQuickSortLP(a []int, lo, hi int) {
65 |
66 | if hi-lo < 2 {
67 | return
68 | }
69 | pivot := parallelPartitionLP(a, lo, hi-1)
70 | basicQuickSortLP(a, lo, pivot)
71 | basicQuickSortLP(a, pivot+1, hi)
72 | }
73 |
--------------------------------------------------------------------------------
/sorts/parallel_quick_sort_of_middle_pivot.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | // This Quick sort is implemented with middle element selected as the pivot
9 |
10 | package sorts
11 |
12 | import (
13 | "runtime"
14 | "sync"
15 | )
16 |
17 | func ParallelQuickSort(a []int) {
18 | runtime.GOMAXPROCS(runtime.NumCPU())
19 | parallelQuickSort(a, 0, len(a))
20 | }
21 |
22 | func parallelQuickSort(a []int, lo, hi int) {
23 |
24 | if hi-lo < 2 {
25 | return
26 | }
27 | pivot := parallelPartition(a, lo, hi-1)
28 | // 2048 is threshold
29 | if hi-lo > 2048 {
30 | var wg sync.WaitGroup
31 | wg.Add(1)
32 |
33 | go func() {
34 | defer wg.Done()
35 | parallelQuickSort(a, lo, pivot)
36 |
37 | }()
38 | parallelQuickSort(a, pivot+1, hi)
39 | wg.Wait()
40 | } else {
41 | basicQuickSort(a, lo, pivot)
42 | basicQuickSort(a, pivot+1, hi)
43 | }
44 | }
45 |
46 | func parallelPartition(a []int, left, right int) int {
47 | lo := left
48 | hi := right
49 | pivot := a[(left+right)>>1]
50 |
51 | for true {
52 | for a[lo] < pivot {
53 | lo++
54 | }
55 | for a[hi] > pivot && lo <= hi {
56 | hi--
57 | }
58 | if lo >= hi {
59 | return hi
60 | }
61 |
62 | a[lo], a[hi] = a[hi], a[lo]
63 | }
64 | return hi
65 | }
66 |
67 | func basicQuickSort(a []int, lo, hi int) {
68 |
69 | if hi-lo < 2 {
70 | return
71 | }
72 | pivot := parallelPartition(a, lo, hi-1)
73 | basicQuickSort(a, lo, pivot)
74 | basicQuickSort(a, pivot+1, hi)
75 | }
76 |
--------------------------------------------------------------------------------
/sorts/parallel_quick_sort_of_right_pivot.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | // This Quick sort is implemented with right element selected as the pivot
9 |
10 | package sorts
11 |
12 | import (
13 | "runtime"
14 | "sync"
15 | )
16 |
17 | func ParallelQuickSortRP(a []int) {
18 | runtime.GOMAXPROCS(runtime.NumCPU())
19 | parallelQuickSortRP(a, 0, len(a))
20 | }
21 |
22 | func parallelQuickSortRP(a []int, lo, hi int) {
23 |
24 | if hi-lo < 2 {
25 | return
26 | }
27 | pivot := parallelPartitionRP(a, lo, hi-1)
28 | // 2048 is threshold
29 | if hi-lo > 2048 {
30 | var wg sync.WaitGroup
31 | wg.Add(1)
32 |
33 | go func() {
34 | defer wg.Done()
35 | parallelQuickSortRP(a, lo, pivot)
36 | }()
37 | parallelQuickSortRP(a, pivot+1, hi)
38 | wg.Wait()
39 |
40 | } else {
41 | basicQuickSortRP(a, lo, pivot)
42 | basicQuickSortRP(a, pivot+1, hi)
43 | }
44 |
45 | }
46 |
47 | func parallelPartitionRP(a []int, left, right int) int {
48 | lo := left
49 | hi := right
50 | pivot := a[right]
51 |
52 | for lo < hi {
53 | for a[lo] < pivot && lo < hi {
54 | lo++
55 | }
56 | for a[hi] >= pivot && lo < hi {
57 | hi--
58 | }
59 |
60 | a[lo], a[hi] = a[hi], a[lo]
61 | }
62 | a[right], a[hi] = a[hi], a[right]
63 | return lo
64 | }
65 |
66 | func basicQuickSortRP(a []int, lo, hi int) {
67 |
68 | if hi-lo < 2 {
69 | return
70 | }
71 | pivot := parallelPartitionRP(a, lo, hi-1)
72 | basicQuickSortRP(a, lo, pivot)
73 | basicQuickSortRP(a, pivot+1, hi)
74 | }
75 |
--------------------------------------------------------------------------------
/simplytest/slice_builder.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import (
11 | crand "crypto/rand"
12 | "fmt"
13 | "math"
14 | "math/big"
15 | "math/rand"
16 | "sort"
17 |
18 | "github.com/logrusorgru/aurora/v3"
19 | )
20 |
21 | func RANDOM_INT(len int) ([]int, []int) {
22 | seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
23 | rand.Seed(seed.Int64())
24 |
25 | var origin, verify []int
26 | fmt.Println(aurora.BrightCyan("[array/slice length : " + fmt.Sprint(len) + "]"))
27 |
28 | fmt.Println("make slice...")
29 | for i := 0; i < len; i++ {
30 | v := rand.Int()
31 |
32 | verify = append(verify, v)
33 | origin = append(origin, v)
34 | }
35 | sort.Ints(verify)
36 | return origin, verify
37 | }
38 |
39 | func DESCENDING_INT(len int) ([]int, []int) {
40 | var origin, verify []int
41 | fmt.Println(aurora.BrightCyan("[array/slice length : " + fmt.Sprint(len) + "]"))
42 |
43 | fmt.Println("make slice...")
44 | for i := 0; i < len; i++ {
45 |
46 | verify = append(verify, len-i)
47 | origin = append(origin, len-i)
48 | }
49 | sort.Ints(verify)
50 | return origin, verify
51 | }
52 |
53 | func ASCENDING_INT(len int) ([]int, []int) {
54 | var origin, verify []int
55 | fmt.Println(aurora.BrightCyan("[array/slice length : " + fmt.Sprint(len) + "]"))
56 |
57 | fmt.Println("make slice...")
58 | for i := 0; i < len; i++ {
59 |
60 | verify = append(verify, i)
61 | origin = append(origin, i)
62 | }
63 | sort.Ints(verify)
64 | return origin, verify
65 | }
66 |
--------------------------------------------------------------------------------
/sorts/parallel_merge_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | import (
11 | "runtime"
12 | "sync"
13 | )
14 |
15 | func ParallelMergeSort(a []int) {
16 | runtime.GOMAXPROCS(runtime.NumCPU())
17 | temp := make([]int, len(a))
18 | parallelMergeSort(a, temp, 0, len(a))
19 | }
20 |
21 | func parallelMergeSort(a, temp []int, left int, right int) {
22 |
23 | if right-left < 2 {
24 | return
25 | }
26 |
27 | // 2048 is threshold
28 | if right-left > 2048 { // parallel
29 |
30 | mid := (left + right) >> 1
31 |
32 | var wg sync.WaitGroup
33 | wg.Add(1)
34 |
35 | go func() {
36 | defer wg.Done()
37 | parallelMergeSort(a, temp, left, mid)
38 | }()
39 |
40 | parallelMergeSort(a, temp, mid, right)
41 | wg.Wait()
42 | mergeForPal(a, temp, left, mid, right)
43 | } else {
44 | basicMergeSort(a, temp, left, right)
45 | }
46 | }
47 |
48 | func basicMergeSort(a, temp []int, left int, right int) {
49 |
50 | if right-left < 2 {
51 | return
52 | }
53 | mid := (left + right) / 2
54 | topDownMergeSort(a, temp, left, mid)
55 | topDownMergeSort(a, temp, mid, right)
56 | mergeForPal(a, temp, left, mid, right)
57 | }
58 |
59 | func mergeForPal(origin, temp []int, left, mid, right int) {
60 | l := left
61 | r := mid
62 | idx := left
63 | for l < mid && r < right {
64 | if origin[l] <= origin[r] {
65 | temp[idx] = origin[l]
66 | idx++
67 | l++
68 | } else {
69 | temp[idx] = origin[r]
70 | idx++
71 | r++
72 | }
73 | }
74 | if l == mid {
75 | for r < right {
76 | temp[idx] = origin[r]
77 | idx++
78 | r++
79 | }
80 | } else {
81 | for l < mid {
82 | temp[idx] = origin[l]
83 | idx++
84 | l++
85 | }
86 | }
87 |
88 | copy(origin[left:], temp[left:right])
89 | }
90 |
--------------------------------------------------------------------------------
/sorts/parallel_dual_pivot_quick_sort.go:
--------------------------------------------------------------------------------
1 | package sorts
2 |
3 | import (
4 | "runtime"
5 | "sync"
6 | )
7 |
8 | func ParallelDualPivotQuickSort(a []int) {
9 | runtime.GOMAXPROCS(runtime.NumCPU())
10 | parallelDualPivotQuickSort(a, 0, len(a))
11 |
12 | }
13 |
14 | func parallelDualPivotQuickSort(a []int, lo, hi int) {
15 |
16 | if hi-lo < 2 {
17 | return
18 | }
19 |
20 | // 4096 is threshold
21 | if hi-lo > 4096 {
22 | var wg sync.WaitGroup
23 | lp, rp := parallel3wayQuickPartition(a, lo, hi-1)
24 | wg.Add(2)
25 | go func() {
26 | defer wg.Done()
27 | parallelDualPivotQuickSort(a, lo, lp)
28 | }()
29 | go func() {
30 | defer wg.Done()
31 | parallelDualPivotQuickSort(a, lp+1, rp)
32 | }()
33 | parallelDualPivotQuickSort(a, rp+1, hi)
34 | wg.Wait()
35 | } else {
36 | basicDualPivotQuickSort(a, lo, hi)
37 | }
38 |
39 | }
40 |
41 | func basicDualPivotQuickSort(a []int, lo, hi int) {
42 |
43 | if hi-lo < 2 {
44 | return
45 | }
46 |
47 | lp, rp := parallel3wayQuickPartition(a, lo, hi-1)
48 | basicDualPivotQuickSort(a, lo, lp)
49 | basicDualPivotQuickSort(a, lp+1, rp)
50 | basicDualPivotQuickSort(a, rp+1, hi)
51 |
52 | }
53 |
54 | func parallel3wayQuickPartition(a []int, lo, hi int) (int, int) {
55 |
56 | if a[lo] > a[hi] {
57 | a[lo], a[hi] = a[hi], a[lo]
58 | }
59 |
60 | l := lo + 1
61 | k := lo + 1
62 | g := hi - 1
63 |
64 | leftPivot := a[lo]
65 | rightPivot := a[hi]
66 |
67 | for k <= g {
68 | if a[k] < leftPivot {
69 | a[k], a[l] = a[l], a[k]
70 | l++
71 | } else if a[k] >= rightPivot {
72 | for rightPivot < a[g] && k < g {
73 | g--
74 | }
75 | a[k], a[g] = a[g], a[k]
76 | g--
77 |
78 | if a[k] < leftPivot {
79 | a[k], a[l] = a[l], a[k]
80 | l++
81 | }
82 | }
83 | k++
84 | }
85 | l--
86 | g++
87 |
88 | a[lo], a[l] = a[l], a[lo]
89 | a[hi], a[g] = a[g], a[hi]
90 |
91 | return l, g
92 | }
93 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # Created by https://www.toptal.com/developers/gitignore/api/macos,go,visualstudiocode,git
3 | # Edit at https://www.toptal.com/developers/gitignore?templates=macos,go,visualstudiocode,git
4 |
5 | ### Git ###
6 | # Created by git for backups. To disable backups in Git:
7 | # $ git config --global mergetool.keepBackup false
8 | *.orig
9 |
10 | # Created by git when using merge tools for conflicts
11 | *.BACKUP.*
12 | *.BASE.*
13 | *.LOCAL.*
14 | *.REMOTE.*
15 | *_BACKUP_*.txt
16 | *_BASE_*.txt
17 | *_LOCAL_*.txt
18 | *_REMOTE_*.txt
19 |
20 | ### Go ###
21 | # Binaries for programs and plugins
22 | *.exe
23 | *.exe~
24 | *.dll
25 | *.so
26 | *.dylib
27 |
28 | main.go
29 |
30 | # Test binary, built with `go test -c`
31 | *.test
32 |
33 | # Output of the go coverage tool, specifically when used with LiteIDE
34 | *.out
35 |
36 | # Dependency directories (remove the comment below to include it)
37 | # vendor/
38 |
39 | ### Go Patch ###
40 | /vendor/
41 | /Godeps/
42 |
43 | ### macOS ###
44 | # General
45 | .DS_Store
46 | .AppleDouble
47 | .LSOverride
48 |
49 | # Icon must end with two \r
50 | Icon
51 |
52 |
53 | # Thumbnails
54 | ._*
55 |
56 | # Files that might appear in the root of a volume
57 | .DocumentRevisions-V100
58 | .fseventsd
59 | .Spotlight-V100
60 | .TemporaryItems
61 | .Trashes
62 | .VolumeIcon.icns
63 | .com.apple.timemachine.donotpresent
64 |
65 | # Directories potentially created on remote AFP share
66 | .AppleDB
67 | .AppleDesktop
68 | Network Trash Folder
69 | Temporary Items
70 | .apdisk
71 |
72 | ### VisualStudioCode ###
73 | .vscode/*
74 | # !.vscode/settings.json
75 | # !.vscode/tasks.json
76 | # !.vscode/launch.json
77 | # !.vscode/extensions.json
78 | # *.code-workspace
79 |
80 | # Local History for Visual Studio Code
81 | .history/
82 |
83 | ### VisualStudioCode Patch ###
84 | # Ignore all local history of files
85 | .history
86 | .ionide
87 |
88 | # Support for Project snippet scope
89 | !.vscode/*.code-snippets
90 |
91 | # End of https://www.toptal.com/developers/gitignore/api/macos,go,visualstudiocode,git
92 |
93 | cl.go
94 |
95 | #bin
96 | GoSortingAlgorithms
--------------------------------------------------------------------------------
/simplytest/option.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | type Activate bool
11 |
12 | // Section 1.
13 | // sorting algorithm test list
14 | const (
15 | BUBBLE_SORT Activate = true
16 | COCKTAIL_SORT Activate = true
17 | INSERTION_SORT Activate = true
18 | SELECTION_SORT Activate = true
19 | SHELL_SORT Activate = true
20 | BOTTOM_UP_MERGE_SORT Activate = true
21 | TOP_DOWN_MERGE_SORT Activate = true
22 | PARALLEL_MERGE_SORT Activate = true
23 | HEAP_SORT Activate = true
24 | LEFT_PIVOT_QUICK_SORT Activate = true
25 | MIDDLE_PIVOT_QUICK_SORT Activate = true
26 | RIGHT_PIVOT_QUICK_SORT Activate = true
27 | PARALLEL_LEFT_PIVOT_QUICK_SORT Activate = true
28 | PARALLEL_MIDDLE_PIVOT_QUICK_SORT Activate = true
29 | PARALLEL_RIGHT_PIVOT_QUICK_SORT Activate = true
30 | DUAL_PIVOT_QUICK_SORT Activate = true
31 | PARALLEL_DUAL_PIVOT_QUICK_SORT Activate = true
32 | BINARY_INSERTION_SORT Activate = true
33 | TIM_SORT Activate = true
34 | BITONIC_SORT Activate = true
35 | PARALLEL_BITONIC_SORT Activate = true
36 | INTRO_SORT Activate = true
37 | PARALLEL_INTRO_SORT Activate = true
38 | CYCLE_SORT Activate = true
39 | ODDEVEN_SORT Activate = true
40 | ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
41 | PARALLEL_ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
42 | COMB_SORT Activate = true
43 | )
44 |
45 | // Section 2.
46 | // The type of slice to be tested.
47 | const (
48 | ASCENDING_TEST Activate = true
49 | RANDOM_TEST Activate = true
50 | DESCENDING_TEST Activate = true
51 | )
52 |
53 | // Section 3.
54 | // lengths for test
55 | var lengths = [...]int{1 << 4, 1 << 7, 1 << 10, 1 << 13, 1 << 16}
56 |
--------------------------------------------------------------------------------
/sorts/intro_sort.go:
--------------------------------------------------------------------------------
1 | package sorts
2 |
3 | import (
4 | "math"
5 | )
6 |
7 | const (
8 | S_THREADHOLD = 16
9 | )
10 |
11 | func IntroSort(a []int) {
12 | introSort(a, 0, len(a))
13 | }
14 |
15 | func introSort(a []int, lo, hi int) {
16 | if hi-lo <= S_THREADHOLD {
17 | __insertionSort(a, lo, hi)
18 | return
19 | }
20 | limit := 2 * int(math.Log2(float64(hi-lo)))
21 | __quickSort(a, lo, hi, limit)
22 | __insertionSort(a, lo, hi)
23 | }
24 |
25 | func __insertionSort(a []int, lo, hi int) {
26 |
27 | for i := lo + 1; i < hi; i++ {
28 | target := a[i]
29 | j := i - 1
30 |
31 | for j >= lo && target < a[j] {
32 | a[j+1] = a[j]
33 | j--
34 | }
35 |
36 | a[j+1] = target
37 | }
38 | }
39 |
40 | func __heapSort(a []int, lo, hi int) {
41 |
42 | if hi-lo < 2 {
43 | return
44 | }
45 | last := hi - 1
46 | parent := ((last - 1) >> 1)
47 |
48 | for parent >= lo {
49 | __heapify(a, parent, last)
50 | parent--
51 | }
52 |
53 | end := hi - 1
54 | for end > lo {
55 | a[lo], a[end] = a[end], a[lo]
56 | end--
57 | __heapify(a, lo, end)
58 | }
59 | }
60 |
61 | func __heapify(a []int, cur, last int) {
62 | var left, right, large int
63 |
64 | for ((cur << 1) + 1) <= last {
65 | left = (cur << 1) + 1
66 | right = (cur << 1) + 2
67 | large = cur
68 |
69 | if a[left] > a[large] {
70 | large = left
71 | }
72 |
73 | if right <= last && a[right] > a[large] {
74 | large = right
75 | }
76 |
77 | if large != cur {
78 | a[cur], a[large] = a[large], a[cur]
79 | cur = large
80 | } else {
81 | return
82 | }
83 | }
84 | }
85 |
86 | func __quickSort(a []int, lo, hi, depthLimit int) {
87 |
88 | if hi-lo <= S_THREADHOLD {
89 | __insertionSort(a, lo, hi)
90 | return
91 | }
92 | if depthLimit == 0 {
93 | __heapSort(a, lo, hi)
94 | return
95 | }
96 | pivot := __partition(a, lo, hi-1)
97 | __quickSort(a, lo, pivot, depthLimit-1)
98 | __quickSort(a, pivot, hi, depthLimit-1)
99 | }
100 |
101 | func __partition(a []int, left, right int) int {
102 | lo := left
103 | hi := right
104 | pivot := a[left+((right-left)>>1)]
105 |
106 | for true {
107 | for a[lo] < pivot {
108 | lo++
109 | }
110 | for a[hi] > pivot && lo <= hi {
111 | hi--
112 | }
113 | if lo >= hi {
114 | return hi
115 | }
116 |
117 | a[lo], a[hi] = a[hi], a[lo]
118 | }
119 | return hi
120 | }
121 |
--------------------------------------------------------------------------------
/sorts/parallel_odd_even_merge_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | import (
11 | "runtime"
12 | "sync"
13 | )
14 |
15 | func ParallelOddEvenMergeSort(a []int) {
16 | runtime.GOMAXPROCS(runtime.NumCPU())
17 | parallelOddEvenMergeSort(a, 0, len(a))
18 | }
19 |
20 | func parallelOddEvenMergeSort(a []int, lo, hi int) {
21 | if hi-lo > 1 {
22 | mid := (hi + lo) >> 1
23 | // 2048 is threshold
24 | if hi-lo > 2048 {
25 |
26 | var wg sync.WaitGroup
27 | wg.Add(1)
28 |
29 | go func() {
30 | defer wg.Done()
31 | parallelOddEvenMergeSort(a, lo, mid)
32 | }()
33 | parallelOddEvenMergeSort(a, mid, hi)
34 | wg.Wait()
35 | parallelOddEvenMerge(a, lo, hi, 1)
36 | } else {
37 | basicOddEvenMergeSort(a, lo, mid)
38 | basicOddEvenMergeSort(a, mid, hi)
39 | basicOddEvenMerge(a, lo, hi, 1)
40 | }
41 | }
42 | }
43 |
44 | func parallelOddEvenMerge(a []int, lo, hi, dist int) {
45 | subDist := dist << 1
46 | if subDist < (hi - lo) {
47 |
48 | if subDist < 32 {
49 | var wg sync.WaitGroup
50 | wg.Add(1)
51 |
52 | go func() {
53 | defer wg.Done()
54 | parallelOddEvenMerge(a, lo, hi, subDist)
55 | }()
56 | parallelOddEvenMerge(a, lo+dist, hi, subDist)
57 | wg.Wait()
58 | } else {
59 | basicOddEvenMerge(a, lo, hi, subDist)
60 | basicOddEvenMerge(a, lo+dist, hi, subDist)
61 | }
62 | for i := lo + dist; i+dist < hi; i += subDist {
63 |
64 | if a[i] > a[i+dist] {
65 | a[i], a[i+dist] = a[i+dist], a[i]
66 | }
67 | }
68 | } else {
69 | if a[lo] > a[lo+dist] {
70 | a[lo], a[lo+dist] = a[lo+dist], a[lo]
71 | }
72 | }
73 | }
74 |
75 | func basicOddEvenMergeSort(a []int, lo, hi int) {
76 | if hi-lo > 1 {
77 | mid := (hi + lo) >> 1
78 | basicOddEvenMergeSort(a, lo, mid)
79 | basicOddEvenMergeSort(a, mid, hi)
80 | basicOddEvenMerge(a, lo, hi, 1)
81 | }
82 | }
83 |
84 | func basicOddEvenMerge(a []int, lo, hi, dist int) {
85 | subDist := dist << 1
86 | if subDist < (hi - lo) {
87 | basicOddEvenMerge(a, lo, hi, subDist)
88 | basicOddEvenMerge(a, lo+dist, hi, subDist)
89 | for i := lo + dist; i+dist < hi; i += subDist {
90 |
91 | if a[i] > a[i+dist] {
92 | a[i], a[i+dist] = a[i+dist], a[i]
93 | }
94 | }
95 | } else {
96 | if a[lo] > a[lo+dist] {
97 | a[lo], a[lo+dist] = a[lo+dist], a[lo]
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/sorts/parallel_bitonic_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | import (
11 | "runtime"
12 | "sync"
13 | )
14 |
15 | func parallelBitonicMerge(a []int, lo, len int, dir bool) {
16 |
17 | if len > 1 {
18 | m := basicGreatestPowerOfTwoLessThan(len)
19 | for i := lo; i < lo+len-m; i++ {
20 | if dir == (a[i] > a[i+m]) {
21 | a[i], a[i+m] = a[i+m], a[i]
22 | }
23 | }
24 | // 2048 is threshold
25 | if len > 2048 { // parallel
26 |
27 | var wg sync.WaitGroup
28 | wg.Add(1)
29 |
30 | go func() {
31 | defer wg.Done()
32 | parallelBitonicMerge(a, lo, m, dir)
33 | }()
34 | parallelBitonicMerge(a, lo+m, len-m, dir)
35 | wg.Wait()
36 | } else {
37 | basicBitonicMerge(a, lo, m, dir)
38 | basicBitonicMerge(a, lo+m, len-m, dir)
39 | }
40 |
41 | }
42 |
43 | }
44 |
45 | func ParallelBitonicSort(a []int) {
46 | runtime.GOMAXPROCS(runtime.NumCPU())
47 | parallelBitonicSort(a, 0, len(a), true)
48 | }
49 |
50 | func parallelBitonicSort(a []int, lo, len int, dir bool) {
51 |
52 | if len > 1 {
53 | mid := len >> 1
54 |
55 | // 2048 is threshold
56 | if len > 2048 { // parallel
57 |
58 | var wg sync.WaitGroup
59 | wg.Add(1)
60 |
61 | go func() {
62 | defer wg.Done()
63 | parallelBitonicSort(a, lo, mid, !dir)
64 | }()
65 |
66 | parallelBitonicSort(a, lo+mid, len-mid, dir)
67 | wg.Wait()
68 | parallelBitonicMerge(a, lo, len, dir)
69 | } else {
70 | basicBitonicSort(a, lo, mid, !dir)
71 | basicBitonicSort(a, lo+mid, len-mid, dir)
72 | basicBitonicMerge(a, lo, len, dir)
73 | }
74 | }
75 | }
76 |
77 | func basicGreatestPowerOfTwoLessThan(n int) int {
78 | k := 1
79 | for k > 0 && k < n {
80 | k <<= 1
81 | }
82 | return k >> 1
83 | }
84 |
85 | func basicBitonicMerge(a []int, lo, len int, dir bool) {
86 | if len > 1 {
87 | m := basicGreatestPowerOfTwoLessThan(len)
88 |
89 | for i := lo; i < lo+len-m; i++ {
90 | if dir == (a[i] > a[i+m]) {
91 | a[i], a[i+m] = a[i+m], a[i]
92 | }
93 | }
94 | basicBitonicMerge(a, lo, m, dir)
95 | basicBitonicMerge(a, lo+m, len-m, dir)
96 | }
97 |
98 | }
99 |
100 | func basicBitonicSort(a []int, lo, len int, dir bool) {
101 |
102 | if len > 1 {
103 | mid := len >> 1
104 | basicBitonicSort(a, lo, mid, !dir)
105 | basicBitonicSort(a, lo+mid, len-mid, dir)
106 | basicBitonicMerge(a, lo, len, dir)
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/sorts/parallel_intro_sort.go:
--------------------------------------------------------------------------------
1 | package sorts
2 |
3 | import (
4 | "math"
5 | "runtime"
6 | "sync"
7 | )
8 |
9 | const (
10 | SIZE_THREADHOLD = 16
11 | T_SIZE_THREADHOLD = 2048
12 | )
13 |
14 | func ParallelIntroSort(a []int) {
15 | parallelIntroSort(a, 0, len(a))
16 | }
17 |
18 | func parallelIntroSort(a []int, lo, hi int) {
19 | if hi-lo <= SIZE_THREADHOLD {
20 | __basicInsertionSort(a, lo, hi)
21 | return
22 | }
23 | runtime.GOMAXPROCS(runtime.NumCPU())
24 | limit := 2 * int(math.Log2(float64(hi-lo)))
25 | __basicParallelQuickSort(a, lo, hi, limit)
26 | __basicInsertionSort(a, lo, hi)
27 | }
28 |
29 | func __basicInsertionSort(a []int, lo, hi int) {
30 |
31 | for i := lo + 1; i < hi; i++ {
32 | target := a[i]
33 | j := i - 1
34 |
35 | for j >= lo && target < a[j] {
36 | a[j+1] = a[j]
37 | j--
38 | }
39 |
40 | a[j+1] = target
41 | }
42 | }
43 |
44 | func __basicHeapSort(a []int, lo, hi int) {
45 |
46 | if hi-lo < 2 {
47 | return
48 | }
49 | last := hi - 1
50 | parent := ((last - 1) >> 1)
51 |
52 | for parent >= lo {
53 | __basicHeapify(a, parent, last)
54 | parent--
55 | }
56 |
57 | end := hi - 1
58 | for end > lo {
59 | a[lo], a[end] = a[end], a[lo]
60 | end--
61 | __basicHeapify(a, lo, end)
62 | }
63 | }
64 |
65 | func __basicHeapify(a []int, cur, last int) {
66 | var left, right, large int
67 |
68 | for ((cur << 1) + 1) <= last {
69 | left = (cur << 1) + 1
70 | right = (cur << 1) + 2
71 | large = cur
72 |
73 | if a[left] > a[large] {
74 | large = left
75 | }
76 |
77 | if right <= last && a[right] > a[large] {
78 | large = right
79 | }
80 |
81 | if large != cur {
82 | a[cur], a[large] = a[large], a[cur]
83 | cur = large
84 | } else {
85 | return
86 | }
87 | }
88 | }
89 |
90 | func __basicParallelQuickSort(a []int, lo, hi, depthLimit int) {
91 |
92 | if hi-lo <= SIZE_THREADHOLD {
93 | __basicInsertionSort(a, lo, hi)
94 | return
95 | }
96 | if depthLimit == 0 {
97 | __basicHeapSort(a, lo, hi)
98 | return
99 | }
100 | pivot := __basicPartition(a, lo, hi-1)
101 | if hi-lo > T_SIZE_THREADHOLD {
102 | var wg sync.WaitGroup
103 | wg.Add(1)
104 | go func() {
105 | defer wg.Done()
106 | __basicParallelQuickSort(a, lo, pivot, depthLimit-1)
107 | }()
108 | __basicParallelQuickSort(a, pivot, hi, depthLimit-1)
109 | wg.Wait()
110 | } else {
111 | __basicQuickSort(a, lo, pivot, depthLimit-1)
112 | __basicQuickSort(a, pivot, hi, depthLimit-1)
113 | }
114 | }
115 |
116 | func __basicQuickSort(a []int, lo, hi, depthLimit int) {
117 |
118 | if hi-lo <= SIZE_THREADHOLD {
119 | __basicInsertionSort(a, lo, hi)
120 | return
121 | }
122 | if depthLimit == 0 {
123 | __basicHeapSort(a, lo, hi)
124 | return
125 | }
126 | pivot := __basicPartition(a, lo, hi-1)
127 | __basicQuickSort(a, lo, pivot, depthLimit-1)
128 | __basicQuickSort(a, pivot, hi, depthLimit-1)
129 | }
130 |
131 | func __basicPartition(a []int, left, right int) int {
132 | lo := left
133 | hi := right
134 | pivot := a[left+((right-left)>>1)]
135 |
136 | for true {
137 | for a[lo] < pivot {
138 | lo++
139 | }
140 | for a[hi] > pivot && lo <= hi {
141 | hi--
142 | }
143 | if lo >= hi {
144 | return hi
145 | }
146 |
147 | a[lo], a[hi] = a[hi], a[lo]
148 | }
149 | return hi
150 | }
151 |
--------------------------------------------------------------------------------
/simplytest/test_run.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import (
11 | "fmt"
12 | "strings"
13 | "time"
14 |
15 | "github.com/logrusorgru/aurora/v3"
16 | )
17 |
18 | type OutputForm struct {
19 | active bool
20 | name string
21 | Time int64
22 | equl bool
23 | err string
24 | }
25 |
26 | type Queue []OutputForm
27 |
28 | func callSortTest(origin, verify []int) {
29 | var q Queue
30 | q = append(q, CallBubbleSort(origin, verify, "bubble sort"))
31 | q = append(q, CallCocktailSort(origin, verify, "cocktail sort"))
32 | q = append(q, CallInsertionSort(origin, verify, "insertion sort"))
33 | q = append(q, CallSelectionSort(origin, verify, "selection sort"))
34 | q = append(q, CallShellSort(origin, verify, "shell sort"))
35 | q = append(q, CallBottomUpMergeSort(origin, verify, "bottom-up merge sort"))
36 | q = append(q, CallTopDownMergeSort(origin, verify, "top-down merge sort"))
37 | q = append(q, CallParallelMergeSort(origin, verify, "parallel merge sort"))
38 | q = append(q, CallHeapSort(origin, verify, "heap sort"))
39 | q = append(q, CallLPQuickSort(origin, verify, "left-pivot quick sort"))
40 | q = append(q, CallQuickSort(origin, verify, "middle-pivot quick sort"))
41 | q = append(q, CallRPQuickSort(origin, verify, "right-pivot quick sort"))
42 | q = append(q, CallParallelLPQuickSort(origin, verify, "parallel left-pivot quick sort"))
43 | q = append(q, CallParallelMPQuickSort(origin, verify, "parallel middle-pivot quick sort"))
44 | q = append(q, CallParallelRPQuickSort(origin, verify, "parallel right-pivot quick sort"))
45 | q = append(q, CallDualPivotQuickSort(origin, verify, "dual-pivot quick sort"))
46 | q = append(q, CallParallelDualPivotQuickSort(origin, verify, "parallel dual-pivot quick sort"))
47 | q = append(q, CallBinaryInsertionSort(origin, verify, "binary insertion sort"))
48 | q = append(q, CallTimSort(origin, verify, "tim sort"))
49 | q = append(q, CallBitonicSort(origin, verify, "bitonic sort"))
50 | q = append(q, CallParallelBitonicSort(origin, verify, "parallel bitonic sort"))
51 | q = append(q, CallIntroSort(origin, verify, "intro sort"))
52 | q = append(q, CallParallelIntroSort(origin, verify, "parallel intro sort"))
53 | q = append(q, CallCycleSort(origin, verify, "cycle sort"))
54 | q = append(q, CallOddEvenSort(origin, verify, "odd-even sort"))
55 | q = append(q, CallOddEvenMergeSort(origin, verify, "odd-even merge sort"))
56 | q = append(q, CallParallelOddEvenMergeSort(origin, verify, "parallel odd-even merge sort"))
57 | q = append(q, CallCombSort(origin, verify, "comb sort"))
58 | var pf string = ""
59 |
60 | pf += fmt.Sprintf("\n+%s+\n", strings.Repeat("-", 97))
61 | pf += fmt.Sprintf("| %35s | %23s | %18s | %10s | \t %s \n", "name", "ns", "ms", "verify", aurora.BrightRed("(err mag)"))
62 |
63 | for _, v := range q {
64 | if v.active {
65 | pf += fmt.Sprintf("|%s|\n", strings.Repeat("-", 97))
66 | if v.equl {
67 | pf += fmt.Sprintf("| %35s | %20d ns | %15d ms | %10t |%s\n", v.name, v.Time, v.Time/int64(time.Millisecond), aurora.BrightGreen(v.equl), v.err)
68 | } else {
69 | pf += fmt.Sprintf("| %35s | %20d ns | %15d ms | %10t |%s\n", v.name, v.Time, v.Time/int64(time.Millisecond), aurora.BrightRed(v.equl), v.err)
70 | }
71 | }
72 | }
73 |
74 | pf += fmt.Sprintf("+%s+\n\n\n", strings.Repeat("-", 97))
75 |
76 | fmt.Print(pf)
77 | }
78 |
--------------------------------------------------------------------------------
/sorts/tim_sort.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package sorts
9 |
10 | type TimStack struct {
11 | array []int
12 | runBase []int
13 | runLen []int
14 | stackSize int
15 | }
16 |
17 | func newTimStack(a []int) *TimStack {
18 | p := TimStack{}
19 | len := len(a)
20 |
21 | var stackLen int
22 |
23 | if len < 120 {
24 | stackLen = 5
25 | } else if len < 1542 {
26 | stackLen = 10
27 | } else if len < 119151 {
28 | stackLen = 19
29 | } else {
30 | stackLen = 40
31 | }
32 | p.runBase = make([]int, stackLen)
33 | p.runLen = make([]int, stackLen)
34 | p.array = a
35 | p.stackSize = 0
36 |
37 | return &p
38 | }
39 |
40 | func (p *TimStack) pushRun(base, len int) {
41 | p.runBase[p.stackSize] = base
42 | p.runLen[p.stackSize] = len
43 | p.stackSize++
44 | }
45 |
46 | func (p *TimStack) mergeForce() {
47 | for p.stackSize > 1 {
48 | if p.stackSize > 2 && p.runLen[p.stackSize-3] < p.runLen[p.stackSize-1] {
49 | p.mergeForTim(p.stackSize - 3)
50 | } else {
51 | p.mergeForTim(p.stackSize - 2)
52 | }
53 | }
54 | }
55 |
56 | func (p *TimStack) mergeBase() {
57 | for p.stackSize > 1 {
58 | if (p.stackSize > 2 && p.runLen[p.stackSize-3] <= p.runLen[p.stackSize-2]+p.runLen[p.stackSize-1]) || (p.stackSize > 3 && p.runLen[p.stackSize-4] <= p.runLen[p.stackSize-3]+p.runLen[p.stackSize-2]) {
59 |
60 | if p.runLen[p.stackSize-3] < p.runLen[p.stackSize-1] {
61 | p.mergeForTim(p.stackSize - 3)
62 | } else {
63 | p.mergeForTim(p.stackSize - 2)
64 | }
65 |
66 | } else if p.runLen[p.stackSize-2] <= p.runLen[p.stackSize-1] {
67 | p.mergeForTim(p.stackSize - 2)
68 | } else {
69 | break
70 | }
71 | }
72 | }
73 |
74 | func (p *TimStack) mergeForTim(idx int) {
75 | start1 := p.runBase[idx]
76 | length1 := p.runLen[idx]
77 | start2 := p.runBase[idx+1]
78 | length2 := p.runLen[idx+1]
79 |
80 | p.runLen[idx] = length1 + length2
81 |
82 | if idx == (p.stackSize - 3) {
83 | p.runBase[idx+1] = p.runBase[idx+2]
84 | p.runLen[idx+1] = p.runLen[idx+2]
85 | }
86 | p.stackSize--
87 |
88 | lo := p.gallopRight(p.array[start2], p.array, start1, length1)
89 | if length1 == lo {
90 | return
91 | }
92 | start1 += lo
93 | length1 -= lo
94 |
95 | hi := p.gallopLeft(p.array[start1+length1-1], p.array, start2, length2)
96 | if hi == 0 {
97 | return
98 | }
99 |
100 | length2 = hi
101 | if length1 <= length2 {
102 | p.mergeLo(start1, length1, start2, length2)
103 | } else {
104 | p.mergeHi(start1, length1, start2, length2)
105 | }
106 | }
107 |
108 | func (p *TimStack) mergeLo(start1, length1, start2, length2 int) {
109 | temp := make([]int, length1)
110 | copy(temp[:length1], p.array[start1:start1+length1])
111 |
112 | insertIdx := start1
113 | runBIdx := start2
114 | tempIdx := 0
115 |
116 | leftRemain := length1
117 | rightRemain := length2
118 |
119 | for leftRemain != 0 && rightRemain != 0 {
120 | if p.array[runBIdx] < temp[tempIdx] {
121 | p.array[insertIdx] = p.array[runBIdx]
122 | insertIdx++
123 | runBIdx++
124 | rightRemain--
125 | } else {
126 | p.array[insertIdx] = temp[tempIdx]
127 | insertIdx++
128 | tempIdx++
129 | leftRemain--
130 | }
131 | }
132 | if leftRemain != 0 {
133 | copy(p.array[insertIdx:], temp[tempIdx:tempIdx+leftRemain])
134 | } else {
135 | copy(p.array[insertIdx:], p.array[runBIdx:runBIdx+rightRemain])
136 | }
137 | }
138 |
139 | func (p *TimStack) mergeHi(start1, length1, start2, length2 int) {
140 | temp := make([]int, length2)
141 | copy(temp, p.array[start2:start2+length2])
142 |
143 | insertIdx := start2 + length2 - 1
144 | runAIdx := start1 + length1 - 1
145 | tempIdx := length2 - 1
146 |
147 | leftRemain := length1
148 | rightRemain := length2
149 |
150 | for leftRemain != 0 && rightRemain != 0 {
151 |
152 | if p.array[runAIdx] > temp[tempIdx] {
153 | p.array[insertIdx] = p.array[runAIdx]
154 | insertIdx--
155 | runAIdx--
156 | leftRemain--
157 | } else {
158 | p.array[insertIdx] = temp[tempIdx]
159 | insertIdx--
160 | tempIdx--
161 | rightRemain--
162 | }
163 | }
164 | if rightRemain != 0 {
165 | copy(p.array[start1:], temp[:rightRemain])
166 | }
167 | }
168 |
169 | func (p *TimStack) gallopRight(key int, array []int, base, lenOfA int) int {
170 | lo := 0
171 | hi := 1
172 |
173 | if key < array[base] {
174 | return 0
175 | }
176 |
177 | maxLen := lenOfA
178 | for hi < maxLen && array[base+hi] <= key {
179 | lo = hi
180 | hi = (hi << 1) + 1
181 | if hi <= 0 {
182 | hi = maxLen
183 | }
184 | }
185 | if hi > maxLen {
186 | hi = maxLen
187 | }
188 |
189 | lo++
190 |
191 | for lo < hi {
192 | mid := lo + ((hi - lo) >> 1)
193 | if key < array[base+mid] {
194 | hi = mid
195 | } else {
196 | lo = mid + 1
197 | }
198 | }
199 | return hi
200 | }
201 |
202 | func (p *TimStack) gallopLeft(key int, array []int, base, lenOfB int) int {
203 | lo := 0
204 | hi := 1
205 |
206 | if key > array[base+lenOfB-1] {
207 | return lenOfB
208 | }
209 |
210 | startPointOfRun := base + lenOfB - 1
211 | maxLen := lenOfB
212 |
213 | for hi < maxLen && key <= array[startPointOfRun-hi] {
214 | lo = hi
215 | hi = (hi << 1) + 1
216 |
217 | if hi <= 0 {
218 | hi = maxLen
219 | }
220 | }
221 |
222 | if hi > maxLen {
223 | hi = maxLen
224 | }
225 |
226 | temp := lo
227 | lo = lenOfB - 1 - hi
228 | hi = lenOfB - 1 - temp
229 |
230 | lo++
231 |
232 | // binary search
233 | for lo < hi {
234 | mid := lo + ((hi - lo) >> 1)
235 |
236 | if key <= array[base+mid] {
237 | hi = mid
238 | } else {
239 | lo = mid + 1
240 | }
241 | }
242 | return hi
243 | }
244 |
245 | func minRunLength(runSize int) int {
246 | r := 0
247 | for runSize >= 32 {
248 | r |= (runSize & 1)
249 | runSize >>= 1
250 | }
251 | return runSize + r
252 | }
253 |
254 | func TimSort(a []int) {
255 | timsort(a, 0, len(a))
256 | }
257 |
258 | func timsort(a []int, lo, hi int) {
259 | remain := hi - lo
260 |
261 | if remain < 2 {
262 | return
263 | }
264 |
265 | if remain < 32 {
266 | increaseRange := getAscending(a, lo, hi)
267 | binarySort(a, lo, hi, lo+increaseRange)
268 | return
269 | }
270 |
271 | ts := newTimStack(a)
272 | minRun := minRunLength(remain)
273 |
274 | for {
275 | runLen := getAscending(a, lo, hi)
276 |
277 | if runLen < minRun {
278 | var counts int
279 | if remain < minRun {
280 | counts = remain
281 | } else {
282 | counts = minRun
283 | }
284 |
285 | binarySort(a, lo, lo+counts, lo+runLen)
286 | runLen = counts
287 | }
288 | ts.pushRun(lo, runLen)
289 | ts.mergeBase()
290 |
291 | lo += runLen
292 | remain -= runLen
293 | if remain == 0 {
294 | break
295 | }
296 | }
297 | ts.mergeForce()
298 | }
299 |
--------------------------------------------------------------------------------
/glob_bench_test/sort_test.go:
--------------------------------------------------------------------------------
1 | package glob_bench_test
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 |
7 | "github.com/kdgyun/GoSortingAlgorithms/simplytest"
8 | "github.com/kdgyun/GoSortingAlgorithms/sorts"
9 | )
10 |
11 | func TestSort(t *testing.T) {
12 | size := 1
13 | for i := 0; i < 6; i++ {
14 | origin, verify := simplytest.RANDOM_INT(size)
15 |
16 | test := make([]int, len(origin))
17 | copy(test, origin)
18 | t.Run("bubble sort", func(t *testing.T) { sorts.BubbleSort(test) })
19 |
20 | if !reflect.DeepEqual(test, verify) {
21 | t.Error("Wrong result [bubble sort]")
22 | }
23 |
24 | test = make([]int, len(origin))
25 | copy(test, origin)
26 | t.Run("cocktail sort", func(t *testing.T) { sorts.CocktailSort(test) })
27 |
28 | if !reflect.DeepEqual(test, verify) {
29 | t.Error("Wrong result [cocktail sort]")
30 | }
31 |
32 | test = make([]int, len(origin))
33 | copy(test, origin)
34 | t.Run("insertion sort", func(t *testing.T) { sorts.InsertionSort(test) })
35 |
36 | if !reflect.DeepEqual(test, verify) {
37 | t.Error("Wrong result [insertion sort]")
38 | }
39 |
40 | test = make([]int, len(origin))
41 | copy(test, origin)
42 | t.Run("selection sort", func(t *testing.T) { sorts.SelectionSort(test) })
43 |
44 | if !reflect.DeepEqual(test, verify) {
45 | t.Error("Wrong result [selection sort]")
46 | }
47 |
48 | test = make([]int, len(origin))
49 | copy(test, origin)
50 | t.Run("shell sort", func(t *testing.T) { sorts.ShellSort(test) })
51 |
52 | if !reflect.DeepEqual(test, verify) {
53 | t.Error("Wrong result [shell sort]")
54 | }
55 |
56 | test = make([]int, len(origin))
57 | copy(test, origin)
58 | t.Run("bottom-up merge sort", func(t *testing.T) { sorts.BottomUpMergeSort(test) })
59 |
60 | if !reflect.DeepEqual(test, verify) {
61 | t.Error("Wrong result [bottom-up merge]")
62 | }
63 |
64 | test = make([]int, len(origin))
65 | copy(test, origin)
66 | t.Run("top-down merge sort", func(t *testing.T) { sorts.TopDownMergeSort(test) })
67 |
68 | if !reflect.DeepEqual(test, verify) {
69 | t.Error("Wrong result [top-down merge]")
70 | }
71 |
72 | test = make([]int, len(origin))
73 | copy(test, origin)
74 | t.Run("parallel merge sort", func(t *testing.T) { sorts.ParallelMergeSort(test) })
75 |
76 | if !reflect.DeepEqual(test, verify) {
77 | t.Error("Wrong result [parallel merge]")
78 | }
79 |
80 | test = make([]int, len(origin))
81 | copy(test, origin)
82 | t.Run("heap sort", func(t *testing.T) { sorts.HeapSort(test) })
83 |
84 | if !reflect.DeepEqual(test, verify) {
85 | t.Error("Wrong result [heap sort]")
86 | }
87 |
88 | test = make([]int, len(origin))
89 | copy(test, origin)
90 | t.Run("left-pivot quick sort", func(t *testing.T) { sorts.QuickSortLP(test) })
91 |
92 | if !reflect.DeepEqual(test, verify) {
93 | t.Error("Wrong result [left-pivot quick sort]")
94 | }
95 |
96 | test = make([]int, len(origin))
97 | copy(test, origin)
98 | t.Run("middle-pivot quick sort", func(t *testing.T) { sorts.QuickSort(test) })
99 |
100 | if !reflect.DeepEqual(test, verify) {
101 | t.Error("Wrong result [middle-pivot quick sort]")
102 | }
103 |
104 | test = make([]int, len(origin))
105 | copy(test, origin)
106 | t.Run("right-pivot quick sort", func(t *testing.T) { sorts.QuickSortRP(test) })
107 |
108 | if !reflect.DeepEqual(test, verify) {
109 | t.Error("Wrong result [right-pivot quick sort]")
110 | }
111 |
112 | test = make([]int, len(origin))
113 | copy(test, origin)
114 | t.Run("parallel left-pivot quick sort", func(t *testing.T) { sorts.ParallelQuickSortLP(test) })
115 |
116 | if !reflect.DeepEqual(test, verify) {
117 | t.Error("Wrong result [parallel left-pivot quick sort]")
118 | }
119 |
120 | test = make([]int, len(origin))
121 | copy(test, origin)
122 | t.Run("parallel middle-pivot quick sort", func(t *testing.T) { sorts.ParallelQuickSort(test) })
123 |
124 | if !reflect.DeepEqual(test, verify) {
125 | t.Error("Wrong result [parallel middle-pivot quick sort]")
126 | }
127 |
128 | test = make([]int, len(origin))
129 | copy(test, origin)
130 | t.Run("parallel right-pivot quick sort", func(t *testing.T) { sorts.ParallelQuickSortRP(test) })
131 |
132 | if !reflect.DeepEqual(test, verify) {
133 | t.Error("Wrong result [parallel right-pivot quick sort]")
134 | }
135 |
136 | test = make([]int, len(origin))
137 | copy(test, origin)
138 | t.Run("dual-pivot quick sort", func(t *testing.T) { sorts.DualPivotQuickSort(test) })
139 |
140 | if !reflect.DeepEqual(test, verify) {
141 | t.Error("Wrong result [dual-pivot quick sort]")
142 | }
143 |
144 | test = make([]int, len(origin))
145 | copy(test, origin)
146 | t.Run("parallel dual-pivot quick sort", func(t *testing.T) { sorts.ParallelDualPivotQuickSort(test) })
147 |
148 | if !reflect.DeepEqual(test, verify) {
149 | t.Error("Wrong result [parallel dual-pivot quick sort]")
150 | }
151 |
152 | test = make([]int, len(origin))
153 | copy(test, origin)
154 | t.Run("binary insertion sort", func(t *testing.T) { sorts.BinarySort(test) })
155 |
156 | if !reflect.DeepEqual(test, verify) {
157 | t.Error("Wrong result [binary insertion sort]")
158 | }
159 |
160 | test = make([]int, len(origin))
161 | copy(test, origin)
162 | t.Run("tim sort", func(t *testing.T) { sorts.TimSort(test) })
163 |
164 | if !reflect.DeepEqual(test, verify) {
165 | t.Error("Wrong result [tim sort]")
166 | }
167 |
168 | test = make([]int, len(origin))
169 | copy(test, origin)
170 | t.Run("bitonic sort", func(t *testing.T) { sorts.BitonicSort(test) })
171 |
172 | if !reflect.DeepEqual(test, verify) {
173 | t.Error("Wrong result [bitonic sort]")
174 | }
175 |
176 | test = make([]int, len(origin))
177 | copy(test, origin)
178 | t.Run("parallel bitonic sort", func(t *testing.T) { sorts.ParallelBitonicSort(test) })
179 |
180 | if !reflect.DeepEqual(test, verify) {
181 | t.Error("Wrong result [parallel bitonic sort]")
182 | }
183 |
184 | test = make([]int, len(origin))
185 | copy(test, origin)
186 | t.Run("intro sort", func(t *testing.T) { sorts.IntroSort(test) })
187 |
188 | if !reflect.DeepEqual(test, verify) {
189 | t.Error("Wrong result [intro sort]")
190 | }
191 |
192 | test = make([]int, len(origin))
193 | copy(test, origin)
194 | t.Run("parallel intro sort", func(t *testing.T) { sorts.ParallelIntroSort(test) })
195 |
196 | if !reflect.DeepEqual(test, verify) {
197 | t.Error("Wrong result [parallel intro sort]")
198 | }
199 |
200 | test = make([]int, len(origin))
201 | copy(test, origin)
202 | t.Run("cycle sort", func(t *testing.T) { sorts.CycleSort(test) })
203 |
204 | if !reflect.DeepEqual(test, verify) {
205 | t.Error("Wrong result [cycle sort]")
206 | }
207 |
208 | test = make([]int, len(origin))
209 | copy(test, origin)
210 | t.Run("odd-even sort", func(t *testing.T) { sorts.OddEvenSort(test) })
211 |
212 | if !reflect.DeepEqual(test, verify) {
213 | t.Error("Wrong result [odd-even sort]")
214 | }
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 |
224 | test = make([]int, len(origin))
225 | copy(test, origin)
226 | t.Run("parallel odd-even merge sort", func(t *testing.T) { sorts.ParallelOddEvenMergeSort(test) })
227 |
228 | if !reflect.DeepEqual(test, verify) {
229 | t.Error("Wrong result [parallel odd-even sort]")
230 | }
231 | size <<= 2
232 | }
233 | }
234 |
--------------------------------------------------------------------------------
/glob_bench_test/sort_bench_test.go:
--------------------------------------------------------------------------------
1 | package glob_bench_test
2 |
3 | import (
4 | "math"
5 | "math/big"
6 | "math/rand"
7 |
8 | crand "crypto/rand"
9 | "testing"
10 |
11 | "github.com/kdgyun/GoSortingAlgorithms/sorts"
12 | )
13 |
14 | var lengthforbench = 1 << 16
15 |
16 | func sliceBuilder(len int) []int {
17 | seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
18 | rand.Seed(seed.Int64())
19 |
20 | var a []int
21 |
22 | for i := 0; i < len; i++ {
23 | v := rand.Int()
24 | a = append(a, v)
25 | }
26 |
27 | return a
28 | }
29 |
30 | func BenchmarkBubbleSort(b *testing.B) {
31 | b.StopTimer()
32 | unsorted := sliceBuilder(lengthforbench)
33 | test := make([]int, len(unsorted))
34 |
35 | for i := 0; i < b.N; i++ {
36 | copy(test, unsorted)
37 | b.StartTimer()
38 | sorts.BubbleSort(test)
39 | b.StopTimer()
40 | }
41 | }
42 |
43 | func BenchmarkCocktailSort(b *testing.B) {
44 | b.StopTimer()
45 | unsorted := sliceBuilder(lengthforbench)
46 | test := make([]int, len(unsorted))
47 |
48 | for i := 0; i < b.N; i++ {
49 | copy(test, unsorted)
50 | b.StartTimer()
51 | sorts.CocktailSort(test)
52 | b.StopTimer()
53 | }
54 | }
55 |
56 | func BenchmarkInsertionSort(b *testing.B) {
57 | b.StopTimer()
58 | unsorted := sliceBuilder(lengthforbench)
59 | test := make([]int, len(unsorted))
60 |
61 | for i := 0; i < b.N; i++ {
62 | copy(test, unsorted)
63 | b.StartTimer()
64 | sorts.InsertionSort(test)
65 | b.StopTimer()
66 | }
67 | }
68 |
69 | func BenchmarkSelectionSort(b *testing.B) {
70 | b.StopTimer()
71 | unsorted := sliceBuilder(lengthforbench)
72 | test := make([]int, len(unsorted))
73 |
74 | for i := 0; i < b.N; i++ {
75 | copy(test, unsorted)
76 | b.StartTimer()
77 | sorts.SelectionSort(test)
78 | b.StopTimer()
79 | }
80 | }
81 |
82 | func BenchmarkShellSort(b *testing.B) {
83 | b.StopTimer()
84 | unsorted := sliceBuilder(lengthforbench)
85 | test := make([]int, len(unsorted))
86 |
87 | for i := 0; i < b.N; i++ {
88 | copy(test, unsorted)
89 | b.StartTimer()
90 | sorts.ShellSort(test)
91 | b.StopTimer()
92 | }
93 | }
94 |
95 | func BenchmarkBottomUpMergeSort(b *testing.B) {
96 | b.StopTimer()
97 | unsorted := sliceBuilder(lengthforbench)
98 | test := make([]int, len(unsorted))
99 |
100 | for i := 0; i < b.N; i++ {
101 | copy(test, unsorted)
102 | b.StartTimer()
103 | sorts.BottomUpMergeSort(test)
104 | b.StopTimer()
105 | }
106 | }
107 |
108 | func BenchmarkTopDownMergeSort(b *testing.B) {
109 | b.StopTimer()
110 | unsorted := sliceBuilder(lengthforbench)
111 | test := make([]int, len(unsorted))
112 |
113 | for i := 0; i < b.N; i++ {
114 | copy(test, unsorted)
115 | b.StartTimer()
116 | sorts.TopDownMergeSort(test)
117 | b.StopTimer()
118 | }
119 | }
120 |
121 | func BenchmarkParallelMergeSort(b *testing.B) {
122 | b.StopTimer()
123 | unsorted := sliceBuilder(lengthforbench)
124 | test := make([]int, len(unsorted))
125 |
126 | for i := 0; i < b.N; i++ {
127 | copy(test, unsorted)
128 | b.StartTimer()
129 | sorts.ParallelMergeSort(test)
130 | b.StopTimer()
131 | }
132 | }
133 |
134 | func BenchmarkHeapSort(b *testing.B) {
135 | b.StopTimer()
136 | unsorted := sliceBuilder(lengthforbench)
137 | test := make([]int, len(unsorted))
138 |
139 | for i := 0; i < b.N; i++ {
140 | copy(test, unsorted)
141 | b.StartTimer()
142 | sorts.HeapSort(test)
143 | b.StopTimer()
144 | }
145 | }
146 |
147 | func BenchmarkQuickSortLP(b *testing.B) {
148 | b.StopTimer()
149 | unsorted := sliceBuilder(lengthforbench)
150 | test := make([]int, len(unsorted))
151 |
152 | for i := 0; i < b.N; i++ {
153 | copy(test, unsorted)
154 | b.StartTimer()
155 | sorts.QuickSortLP(test)
156 | b.StopTimer()
157 | }
158 | }
159 |
160 | func BenchmarkQuickSort(b *testing.B) {
161 | b.StopTimer()
162 | unsorted := sliceBuilder(lengthforbench)
163 | test := make([]int, len(unsorted))
164 |
165 | for i := 0; i < b.N; i++ {
166 | copy(test, unsorted)
167 | b.StartTimer()
168 | sorts.QuickSort(test)
169 | b.StopTimer()
170 | }
171 | }
172 |
173 | func BenchmarkQuickSortRP(b *testing.B) {
174 | b.StopTimer()
175 | unsorted := sliceBuilder(lengthforbench)
176 | test := make([]int, len(unsorted))
177 |
178 | for i := 0; i < b.N; i++ {
179 | copy(test, unsorted)
180 | b.StartTimer()
181 | sorts.QuickSortRP(test)
182 | b.StopTimer()
183 | }
184 | }
185 |
186 | func BenchmarkParallelQuickSortLP(b *testing.B) {
187 | b.StopTimer()
188 | unsorted := sliceBuilder(lengthforbench)
189 | test := make([]int, len(unsorted))
190 |
191 | for i := 0; i < b.N; i++ {
192 | copy(test, unsorted)
193 | b.StartTimer()
194 | sorts.ParallelQuickSortLP(test)
195 | b.StopTimer()
196 | }
197 | }
198 |
199 | func BenchmarkParallelQuickSort(b *testing.B) {
200 | b.StopTimer()
201 | unsorted := sliceBuilder(lengthforbench)
202 | test := make([]int, len(unsorted))
203 |
204 | for i := 0; i < b.N; i++ {
205 | copy(test, unsorted)
206 | b.StartTimer()
207 | sorts.ParallelQuickSort(test)
208 | b.StopTimer()
209 | }
210 | }
211 |
212 | func BenchmarkParallelQuickSortRP(b *testing.B) {
213 | b.StopTimer()
214 | unsorted := sliceBuilder(lengthforbench)
215 | test := make([]int, len(unsorted))
216 |
217 | for i := 0; i < b.N; i++ {
218 | copy(test, unsorted)
219 | b.StartTimer()
220 | sorts.ParallelQuickSortRP(test)
221 | b.StopTimer()
222 | }
223 | }
224 |
225 | func BenchmarkDualPivotQuickSort(b *testing.B) {
226 | b.StopTimer()
227 | unsorted := sliceBuilder(lengthforbench)
228 | test := make([]int, len(unsorted))
229 |
230 | for i := 0; i < b.N; i++ {
231 | copy(test, unsorted)
232 | b.StartTimer()
233 | sorts.DualPivotQuickSort(test)
234 | b.StopTimer()
235 | }
236 | }
237 |
238 | func BenchmarkParallelDualPivotQuickSort(b *testing.B) {
239 | b.StopTimer()
240 | unsorted := sliceBuilder(lengthforbench)
241 | test := make([]int, len(unsorted))
242 |
243 | for i := 0; i < b.N; i++ {
244 | copy(test, unsorted)
245 | b.StartTimer()
246 | sorts.ParallelDualPivotQuickSort(test)
247 | b.StopTimer()
248 | }
249 | }
250 |
251 | func BenchmarkBinarySort(b *testing.B) {
252 | b.StopTimer()
253 | unsorted := sliceBuilder(lengthforbench)
254 | test := make([]int, len(unsorted))
255 |
256 | for i := 0; i < b.N; i++ {
257 | copy(test, unsorted)
258 | b.StartTimer()
259 | sorts.BinarySort(test)
260 | b.StopTimer()
261 | }
262 | }
263 |
264 | func BenchmarkTimSort(b *testing.B) {
265 | b.StopTimer()
266 | unsorted := sliceBuilder(lengthforbench)
267 | test := make([]int, len(unsorted))
268 |
269 | for i := 0; i < b.N; i++ {
270 | copy(test, unsorted)
271 | b.StartTimer()
272 | sorts.TimSort(test)
273 | b.StopTimer()
274 | }
275 | }
276 |
277 | func BenchmarkBitonicSort(b *testing.B) {
278 | b.StopTimer()
279 | unsorted := sliceBuilder(lengthforbench)
280 | test := make([]int, len(unsorted))
281 |
282 | for i := 0; i < b.N; i++ {
283 | copy(test, unsorted)
284 | b.StartTimer()
285 | sorts.BitonicSort(test)
286 | b.StopTimer()
287 | }
288 | }
289 |
290 | func BenchmarkParallelBitonicSort(b *testing.B) {
291 | b.StopTimer()
292 | unsorted := sliceBuilder(lengthforbench)
293 | test := make([]int, len(unsorted))
294 |
295 | for i := 0; i < b.N; i++ {
296 | copy(test, unsorted)
297 | b.StartTimer()
298 | sorts.ParallelBitonicSort(test)
299 | b.StopTimer()
300 | }
301 | }
302 |
303 | func BenchmarkIntroSort(b *testing.B) {
304 | b.StopTimer()
305 | unsorted := sliceBuilder(lengthforbench)
306 | test := make([]int, len(unsorted))
307 |
308 | for i := 0; i < b.N; i++ {
309 | copy(test, unsorted)
310 | b.StartTimer()
311 | sorts.IntroSort(test)
312 | b.StopTimer()
313 | }
314 | }
315 |
316 | func BenchmarkParallelIntroSort(b *testing.B) {
317 | b.StopTimer()
318 | unsorted := sliceBuilder(lengthforbench)
319 | test := make([]int, len(unsorted))
320 |
321 | for i := 0; i < b.N; i++ {
322 | copy(test, unsorted)
323 | b.StartTimer()
324 | sorts.ParallelIntroSort(test)
325 | b.StopTimer()
326 | }
327 | }
328 |
329 | func BenchmarkCycleSort(b *testing.B) {
330 | b.StopTimer()
331 | unsorted := sliceBuilder(lengthforbench)
332 | test := make([]int, len(unsorted))
333 |
334 | for i := 0; i < b.N; i++ {
335 | copy(test, unsorted)
336 | b.StartTimer()
337 | sorts.CycleSort(test)
338 | b.StopTimer()
339 | }
340 | }
341 |
342 | func BenchmarkOddEvenSort(b *testing.B) {
343 | b.StopTimer()
344 | unsorted := sliceBuilder(lengthforbench)
345 | test := make([]int, len(unsorted))
346 |
347 | for i := 0; i < b.N; i++ {
348 | copy(test, unsorted)
349 | b.StartTimer()
350 | sorts.OddEvenSort(test)
351 | b.StopTimer()
352 | }
353 | }
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 | }
367 |
368 | func BenchmarkParallelOddEvenMergeSort(b *testing.B) {
369 | b.StopTimer()
370 | unsorted := sliceBuilder(lengthforbench)
371 | test := make([]int, len(unsorted))
372 |
373 | for i := 0; i < b.N; i++ {
374 | copy(test, unsorted)
375 | b.StartTimer()
376 | sorts.ParallelOddEvenMergeSort(test)
377 | b.StopTimer()
378 | }
379 | }
380 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [2023] [kdgyun]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/simplytest/base_sort_list.go:
--------------------------------------------------------------------------------
1 | /*
2 | author : kdgyun
3 |
4 | link : https://st-lab.tistory.com
5 | link : https://github.com/kdgyun
6 | */
7 |
8 | package simplytest
9 |
10 | import (
11 | "fmt"
12 | "time"
13 |
14 | "github.com/kdgyun/GoSortingAlgorithms/sorts"
15 | "github.com/logrusorgru/aurora/v3"
16 | )
17 |
18 | func CallBubbleSort(origin []int, verify []int, callName string) OutputForm {
19 | if BUBBLE_SORT {
20 | test := make([]int, len(origin))
21 | copy(test, origin)
22 | fmt.Printf("running %s...\n", callName)
23 | start := time.Now()
24 | sorts.BubbleSort(test)
25 | end := time.Since(start)
26 | eq, err := Equal(verify, test)
27 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
28 | }
29 | return OutputForm{false, callName, -1, false, ""}
30 | }
31 |
32 | func CallCocktailSort(origin []int, verify []int, callName string) OutputForm {
33 | if COCKTAIL_SORT {
34 | test := make([]int, len(origin))
35 | copy(test, origin)
36 | fmt.Printf("running %s...\n", callName)
37 | start := time.Now()
38 | sorts.CocktailSort(test)
39 | end := time.Since(start)
40 | eq, err := Equal(verify, test)
41 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
42 | }
43 | return OutputForm{false, callName, -1, false, ""}
44 | }
45 |
46 | func CallInsertionSort(origin []int, verify []int, callName string) OutputForm {
47 | if INSERTION_SORT {
48 | test := make([]int, len(origin))
49 | copy(test, origin)
50 | fmt.Printf("running %s...\n", callName)
51 | start := time.Now()
52 | sorts.InsertionSort(test)
53 | end := time.Since(start)
54 | eq, err := Equal(verify, test)
55 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
56 | }
57 | return OutputForm{false, callName, -1, false, ""}
58 | }
59 |
60 | func CallSelectionSort(origin []int, verify []int, callName string) OutputForm {
61 | if SELECTION_SORT {
62 | test := make([]int, len(origin))
63 | copy(test, origin)
64 | fmt.Printf("running %s...\n", callName)
65 | start := time.Now()
66 | sorts.SelectionSort(test)
67 | end := time.Since(start)
68 | eq, err := Equal(verify, test)
69 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
70 | }
71 | return OutputForm{false, callName, -1, false, ""}
72 | }
73 |
74 | func CallShellSort(origin []int, verify []int, callName string) OutputForm {
75 | if SHELL_SORT {
76 | test := make([]int, len(origin))
77 | copy(test, origin)
78 | fmt.Printf("running %s...\n", callName)
79 | start := time.Now()
80 | sorts.ShellSort(test)
81 | end := time.Since(start)
82 | eq, err := Equal(verify, test)
83 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
84 | }
85 | return OutputForm{false, callName, -1, false, ""}
86 | }
87 |
88 | func CallBottomUpMergeSort(origin []int, verify []int, callName string) OutputForm {
89 | if BOTTOM_UP_MERGE_SORT {
90 | test := make([]int, len(origin))
91 | copy(test, origin)
92 | fmt.Printf("running %s...\n", callName)
93 | start := time.Now()
94 | sorts.BottomUpMergeSort(test)
95 | end := time.Since(start)
96 | eq, err := Equal(verify, test)
97 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
98 | }
99 | return OutputForm{false, callName, -1, false, ""}
100 | }
101 |
102 | func CallTopDownMergeSort(origin []int, verify []int, callName string) OutputForm {
103 | if TOP_DOWN_MERGE_SORT {
104 | test := make([]int, len(origin))
105 | copy(test, origin)
106 | fmt.Printf("running %s...\n", callName)
107 | start := time.Now()
108 | sorts.TopDownMergeSort(test)
109 | end := time.Since(start)
110 | eq, err := Equal(verify, test)
111 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
112 | }
113 | return OutputForm{false, callName, -1, false, ""}
114 | }
115 |
116 | func CallParallelMergeSort(origin []int, verify []int, callName string) OutputForm {
117 | if PARALLEL_MERGE_SORT {
118 | test := make([]int, len(origin))
119 | copy(test, origin)
120 | fmt.Printf("running %s...\n", callName)
121 | start := time.Now()
122 | sorts.ParallelMergeSort(test)
123 | end := time.Since(start)
124 | eq, err := Equal(verify, test)
125 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
126 | }
127 | return OutputForm{false, callName, -1, false, ""}
128 | }
129 |
130 | func CallHeapSort(origin []int, verify []int, callName string) OutputForm {
131 | if HEAP_SORT {
132 | test := make([]int, len(origin))
133 | copy(test, origin)
134 | fmt.Printf("running %s...\n", callName)
135 | start := time.Now()
136 | sorts.HeapSort(test)
137 | end := time.Since(start)
138 | eq, err := Equal(verify, test)
139 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
140 | }
141 | return OutputForm{false, callName, -1, false, ""}
142 | }
143 |
144 | func CallLPQuickSort(origin []int, verify []int, callName string) OutputForm {
145 | if LEFT_PIVOT_QUICK_SORT {
146 | test := make([]int, len(origin))
147 | copy(test, origin)
148 | fmt.Printf("running %s...\n", callName)
149 | start := time.Now()
150 | sorts.QuickSortLP(test)
151 | end := time.Since(start)
152 | eq, err := Equal(verify, test)
153 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
154 | }
155 | return OutputForm{false, callName, -1, false, ""}
156 | }
157 |
158 | func CallQuickSort(origin []int, verify []int, callName string) OutputForm {
159 | if MIDDLE_PIVOT_QUICK_SORT {
160 | test := make([]int, len(origin))
161 | copy(test, origin)
162 | fmt.Printf("running %s...\n", callName)
163 | start := time.Now()
164 | sorts.QuickSort(test)
165 | end := time.Since(start)
166 | eq, err := Equal(verify, test)
167 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
168 | }
169 | return OutputForm{false, callName, -1, false, ""}
170 | }
171 |
172 | func CallRPQuickSort(origin []int, verify []int, callName string) OutputForm {
173 | if RIGHT_PIVOT_QUICK_SORT {
174 | test := make([]int, len(origin))
175 | copy(test, origin)
176 | fmt.Printf("running %s...\n", callName)
177 | start := time.Now()
178 | sorts.QuickSortRP(test)
179 | end := time.Since(start)
180 | eq, err := Equal(verify, test)
181 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
182 | }
183 | return OutputForm{false, callName, -1, false, ""}
184 | }
185 |
186 | func CallParallelLPQuickSort(origin []int, verify []int, callName string) OutputForm {
187 | if PARALLEL_LEFT_PIVOT_QUICK_SORT {
188 | test := make([]int, len(origin))
189 | copy(test, origin)
190 | fmt.Printf("running %s...\n", callName)
191 | start := time.Now()
192 | sorts.ParallelQuickSortLP(test)
193 | end := time.Since(start)
194 | eq, err := Equal(verify, test)
195 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
196 | }
197 | return OutputForm{false, callName, -1, false, ""}
198 | }
199 |
200 | func CallParallelMPQuickSort(origin []int, verify []int, callName string) OutputForm {
201 | if PARALLEL_MIDDLE_PIVOT_QUICK_SORT {
202 | test := make([]int, len(origin))
203 | copy(test, origin)
204 | fmt.Printf("running %s...\n", callName)
205 | start := time.Now()
206 | sorts.ParallelQuickSort(test)
207 | end := time.Since(start)
208 | eq, err := Equal(verify, test)
209 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
210 | }
211 | return OutputForm{false, callName, -1, false, ""}
212 | }
213 |
214 | func CallParallelRPQuickSort(origin []int, verify []int, callName string) OutputForm {
215 | if PARALLEL_RIGHT_PIVOT_QUICK_SORT {
216 | test := make([]int, len(origin))
217 | copy(test, origin)
218 | fmt.Printf("running %s...\n", callName)
219 | start := time.Now()
220 | sorts.ParallelQuickSortRP(test)
221 | end := time.Since(start)
222 | eq, err := Equal(verify, test)
223 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
224 | }
225 | return OutputForm{false, callName, -1, false, ""}
226 | }
227 |
228 | func CallDualPivotQuickSort(origin []int, verify []int, callName string) OutputForm {
229 | if DUAL_PIVOT_QUICK_SORT {
230 | test := make([]int, len(origin))
231 | copy(test, origin)
232 | fmt.Printf("running %s...\n", callName)
233 | start := time.Now()
234 | sorts.DualPivotQuickSort(test)
235 | end := time.Since(start)
236 | eq, err := Equal(verify, test)
237 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
238 | }
239 | return OutputForm{false, callName, -1, false, ""}
240 | }
241 |
242 | func CallParallelDualPivotQuickSort(origin []int, verify []int, callName string) OutputForm {
243 | if PARALLEL_DUAL_PIVOT_QUICK_SORT {
244 | test := make([]int, len(origin))
245 | copy(test, origin)
246 | fmt.Printf("running %s...\n", callName)
247 | start := time.Now()
248 | sorts.ParallelDualPivotQuickSort(test)
249 | end := time.Since(start)
250 | eq, err := Equal(verify, test)
251 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
252 | }
253 | return OutputForm{false, callName, -1, false, ""}
254 | }
255 |
256 | func CallBinaryInsertionSort(origin []int, verify []int, callName string) OutputForm {
257 | if BINARY_INSERTION_SORT {
258 | test := make([]int, len(origin))
259 | copy(test, origin)
260 | fmt.Printf("running %s...\n", callName)
261 | start := time.Now()
262 | sorts.BinarySort(test)
263 | end := time.Since(start)
264 | eq, err := Equal(verify, test)
265 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
266 | }
267 | return OutputForm{false, callName, -1, false, ""}
268 | }
269 |
270 | func CallTimSort(origin []int, verify []int, callName string) OutputForm {
271 | if TIM_SORT {
272 | test := make([]int, len(origin))
273 | copy(test, origin)
274 | fmt.Printf("running %s...\n", callName)
275 | start := time.Now()
276 | sorts.TimSort(test)
277 | end := time.Since(start)
278 | eq, err := Equal(verify, test)
279 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
280 | }
281 | return OutputForm{false, callName, -1, false, ""}
282 | }
283 |
284 | func CallBitonicSort(origin []int, verify []int, callName string) OutputForm {
285 | if BITONIC_SORT {
286 | test := make([]int, len(origin))
287 | copy(test, origin)
288 | fmt.Printf("running %s...\n", callName)
289 | start := time.Now()
290 | sorts.BitonicSort(test)
291 | end := time.Since(start)
292 | eq, err := Equal(verify, test)
293 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
294 | }
295 | return OutputForm{false, callName, -1, false, ""}
296 | }
297 |
298 | func CallParallelBitonicSort(origin []int, verify []int, callName string) OutputForm {
299 | if PARALLEL_BITONIC_SORT {
300 | test := make([]int, len(origin))
301 | copy(test, origin)
302 | fmt.Printf("running %s...\n", callName)
303 | start := time.Now()
304 | sorts.ParallelBitonicSort(test)
305 | end := time.Since(start)
306 | eq, err := Equal(verify, test)
307 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
308 | }
309 | return OutputForm{false, callName, -1, false, ""}
310 | }
311 |
312 | func CallIntroSort(origin []int, verify []int, callName string) OutputForm {
313 | if INTRO_SORT {
314 | test := make([]int, len(origin))
315 | copy(test, origin)
316 | fmt.Printf("running %s...\n", callName)
317 | start := time.Now()
318 | sorts.IntroSort(test)
319 | end := time.Since(start)
320 | eq, err := Equal(verify, test)
321 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
322 | }
323 | return OutputForm{false, callName, -1, false, ""}
324 | }
325 |
326 | func CallParallelIntroSort(origin []int, verify []int, callName string) OutputForm {
327 | if PARALLEL_INTRO_SORT {
328 | test := make([]int, len(origin))
329 | copy(test, origin)
330 | fmt.Printf("running %s...\n", callName)
331 | start := time.Now()
332 | sorts.ParallelIntroSort(test)
333 | end := time.Since(start)
334 | eq, err := Equal(verify, test)
335 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
336 | }
337 | return OutputForm{false, callName, -1, false, ""}
338 | }
339 |
340 | func CallCycleSort(origin []int, verify []int, callName string) OutputForm {
341 | if CYCLE_SORT {
342 | test := make([]int, len(origin))
343 | copy(test, origin)
344 | fmt.Printf("running %s...\n", callName)
345 | start := time.Now()
346 | sorts.CycleSort(test)
347 | end := time.Since(start)
348 | eq, err := Equal(verify, test)
349 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
350 | }
351 | return OutputForm{false, callName, -1, false, ""}
352 | }
353 |
354 | func CallOddEvenSort(origin []int, verify []int, callName string) OutputForm {
355 | if ODDEVEN_SORT {
356 | test := make([]int, len(origin))
357 | copy(test, origin)
358 | fmt.Printf("running %s...\n", callName)
359 | start := time.Now()
360 | sorts.OddEvenSort(test)
361 | end := time.Since(start)
362 | eq, err := Equal(verify, test)
363 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
364 | }
365 | return OutputForm{false, callName, -1, false, ""}
366 | }
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("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("running %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 | }
387 |
388 | func CallParallelOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
389 | size := len(origin)
390 | if (size & (size - 1)) != 0 {
391 | fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("parallel odd-even sort can't run"))
392 | fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
393 | return OutputForm{false, callName, -1, false, ""}
394 | }
395 | if PARALLEL_ODDEVEN_MERGE_SORT {
396 | test := make([]int, len(origin))
397 | copy(test, origin)
398 | fmt.Printf("running %s...\n", callName)
399 | start := time.Now()
400 | sorts.ParallelOddEvenMergeSort(test)
401 | end := time.Since(start)
402 | eq, err := Equal(verify, test)
403 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
404 | }
405 | return OutputForm{false, callName, -1, false, ""}
406 | }
407 |
408 | func CallCombSort(origin []int, verify []int, callName string) OutputForm {
409 | if COMB_SORT {
410 | test := make([]int, len(origin))
411 | copy(test, origin)
412 | fmt.Printf("running %s...\n", callName)
413 | start := time.Now()
414 | sorts.CombSort(test)
415 | end := time.Since(start)
416 | eq, err := Equal(verify, test)
417 | return OutputForm{true, callName, end.Nanoseconds(), eq, err}
418 | }
419 | return OutputForm{false, callName, -1, false, ""}
420 | }
421 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | **한글 문서** | **[English Document](./README-en.md)**
2 |
3 |
4 |
5 | 
6 | 
7 | 
8 | 
9 | 
10 |
11 | # GoSortingAlgorithms
12 |
13 |
14 |
15 | Go 언어로 작성된 다양한 정렬 알고리즘들이 있습니다 :octocat:
16 |
17 |
18 |
19 |
20 | ## :beginner: 설치 방법
21 |
22 | Go 언어가 설치 되어 있다면, go get 명령어를 실행하여 GoSoringAlgorithms 패키지를 받아옵니다.
23 |
24 | ```shell
25 | $ go get github.com/kdgyun/GoSortingAlgorithms
26 | ```
27 |
28 |
29 |
30 |
31 | ## :book: 사용 설명서
32 |
33 | 간단합니다!
34 |
35 | ```go
36 |
37 | package main
38 |
39 | import (
40 | "github.com/kdgyun/GoSortingAlgorithms/sorts"
41 |
42 | crand "crypto/rand"
43 | "fmt"
44 | "math"
45 | "math/big"
46 | "math/rand"
47 | "sort"
48 | )
49 |
50 | // 랜덤 정수 슬라이스 생성기
51 | func SliceBuilder(len int) []int {
52 | seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
53 | rand.Seed(seed.Int64())
54 |
55 | var slice []int
56 | for i := 0; i < len; i++ {
57 | slice = append(slice, rand.Int())
58 | }
59 | return slice
60 | }
61 |
62 | func main() {
63 | slice := SliceBuilder(1000000)
64 |
65 | sorts.QuickSort(slice) // sorts.____(slice []int)
66 |
67 | isSorted := sort.SliceIsSorted(slice, func(i, j int) bool {
68 | return slice[i] < slice[j]
69 | })
70 | fmt.Print(isSorted)
71 | }
72 |
73 | ```
74 |
75 |
76 |
77 |
78 |
79 | ## :test_tube: 간단한 테스트 방법
80 |
81 | symplytest 를 통해 쉽게 테스트 할 수 있습니다.
82 |
83 | ```go
84 |
85 | package main
86 |
87 | import (
88 | "github.com/kdgyun/GoSortingAlgorithms/simplytest"
89 | )
90 |
91 | func main() {
92 | simplytest.RunTest()
93 | }
94 |
95 |
96 | ```
97 |
98 |
99 |
100 |
101 | 출력 예시
102 |
103 | ```
104 |
105 | +==================================================================================+
106 | | Random Test |
107 | +==================================================================================+
108 |
109 | ...
110 |
111 | [array length : 100000]
112 | make arrays...
113 | running bubble sort...
114 | running cocktail sort...
115 |
116 | ...
117 |
118 | running intro sort...
119 | running parallel intro sort...
120 | running cycle sort...
121 |
122 | +-------------------------------------------------------------------------------------------------+
123 | | name | ns | ms | verify | (err mag)
124 | |-------------------------------------------------------------------------------------------------|
125 | | bubble sort | 13016202738 ns | 13016 ms | true |
126 | |-------------------------------------------------------------------------------------------------|
127 | | cocktail sort | 8922656474 ns | 8922 ms | true |
128 | |-------------------------------------------------------------------------------------------------|
129 | | tim sort | 11419013 ns | 11 ms | true |
130 | |-------------------------------------------------------------------------------------------------|
131 | | bitonic sort | 32333072 ns | 32 ms | true |
132 | |-------------------------------------------------------------------------------------------------|
133 |
134 | ...
135 |
136 | |-------------------------------------------------------------------------------------------------|
137 | | intro sort | 6665792 ns | 6 ms | true |
138 | |-------------------------------------------------------------------------------------------------|
139 | | parallel intro sort | 2537508 ns | 2 ms | true |
140 | |-------------------------------------------------------------------------------------------------|
141 | | cycle sort | 20209957747 ns | 20209 ms | true |
142 | +-------------------------------------------------------------------------------------------------+
143 |
144 | ```
145 |
146 |
147 |
148 |
149 |
150 |
151 | ### Option
152 |
153 | ```option.go```를 통해 사용자가 쉽게 테스트 형식을 조정할 수 있으며, 3가지 주요 옵션을 제공합니다.
154 |
155 |
156 | 1. 정렬 알고리즘 선택
157 | 특정 정렬 알고리즘만 테스트 혹은 제외하고자 한다면 테스트하고자 하는 정렬 알고리즘 이름을 찾아 변수를 true 또는 false로 변경합니다. (True : 테스트 허용, false : 테스트 비허용)
158 | > ex) SHELL_SORT Activate = true
159 |
160 | 2. 테스트 할 슬라이스의 길이 변경.
161 | 테스트할 슬라이스의 길이를 변경하려면 'lengths' 변수의 슬라이스를 원하는 값으로 설정 할 수 있습니다. 아래 예시는 길이 35, 50,000, 100,000 슬라이스에 대해 각각 테스트 하게 됩니다.
162 | > ex) var lengths = [...]int{35, 50000, 100000}
163 |
164 |
165 | 3. 슬라이스 유형 변경.
166 | 기본적으로 오름차순, 내림차순 및 랜덤 데이터로 구성된 각각의 모든 슬라이스가 테스트됩니다. 그러나 특정 데이터 유형을 비활성화하려면 변수를 false로 변경하면 됩니다.
167 | > ex) ASCENDING_TEST Activate = false
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 | ## :mag_right: 개요
178 |
179 |
180 |
181 | Go 언어는 배열과 슬라이스가 구분되어 있습니다. 하지만, 일반적으로 기타 언어에서도 배열이 익숙하기 때문에 해당 알고리즘을 설명 할 때에는 **배열**로 통일하여 설명합니다.
182 |
183 | 현재 업데이트 된 정렬 알고리즘:
184 |
185 | | name | function name |
186 | | --- | :-: |
187 | | [Bubble Sort](#bubble-sort) | BubbleSort |
188 | | [Cocktail Sort](#cocktail-sort) | CocktailSort |
189 | | [Insertion Sort](#insertion-sort) | InsertionSort |
190 | | [Selection Sort](#selection-sort) | SelectionSort |
191 | | [Shell Sort](#shell-sort) | ShellSort |
192 | | [Merge Sort (bottom-up)](#merge-sort) | BottomUpMergeSort |
193 | | [Merge Sort (top-down)](#merge-sort) | TopDownMergeSort |
194 | | [Merge Sort (parallel)](#merge-sort) | ParallelMergeSort |
195 | | [Heap Sort](#heap-sort) | HeapSort |
196 | | [Quick Sort (left-pivot)](#quick-sort) | QuickSortLP |
197 | | [Quick Sort (middle-pivot)](#quick-sort) | QuickSort |
198 | | [Quick Sort (left-pivot)](#quick-sort) | QuickSortRP |
199 | | [Quick Sort (left-pivot with parallel)](#quick-sort) | ParallelQuickSortLP |
200 | | [Quick Sort (middle-pivot with parallel)](#quick-sort) | ParallelQuickSort |
201 | | [Quick Sort (left-pivot with parallel)](#quick-sort) | ParallelQuickSortRP |
202 | | [Dual-pivot Quick Sort](#dual-pivot-quick-sort) | DualPivotQuickSort |
203 | | [Dual-pivot Quick Sort (parallel)](#dual-pivot-quick-sort) | ParallelDualPivotQuickSort |
204 | | [Binaray Insertion Sort](#binary-insertion-sort) | BinarySort |
205 | | [Tim Sort](#tim-sort) | TimSort |
206 | | [Bitonic Sort](#bitonic-sort) | BitonicSort |
207 | | [Bitonic Sort (parallel)](#bitonic-sort) | ParallelBitonicSort |
208 | | [Intro Sort](#intro-sort) | IntroSort |
209 | | [Intro Sort (parallel)](#intro-sort) | ParallelIntroSort |
210 | | [Cycle Sort](#cycle-sort) | CycleSort |
211 | | [Odd-Even Sort](#odd-even-sort) | OddEvenSort |
212 | | [Odd-Even Merge Sort](#odd-even-merge-sort) | OddEvenMergeSort |
213 | | [Odd-Even Merge Sort (parallel)](#odd-even-merge-sort) | ParallelOddEvenMergeSort |
214 | | [Comb Sort](#comb-sort) | CombSort |
215 |
216 |
217 |
218 |
219 |
220 | ## Bubble Sort
221 |
222 |
223 | 버블 정렬은 인접한 요소를 반복적으로 비교하고 교환하는 방식입니다.
224 | 해당 구현은 이미 배열이 정렬되어있는 경우 정렬을 종료하도록 최적화되어 있습니다. 최적화를 원하지 않는다면, bubbleSort 함수에서 swapped 변수를 삭제 및 해당 조건문을 삭제하면 됩니다.
225 |
226 | ### COMPLEXITY
227 |
228 |
229 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
230 | | :-: | :-: | :-: | :-: | :-: | :-: |
231 | | ) | ) | ) or ) | Yes | Yes | total : ), auxiliary : ) |
232 |
233 |
234 |
235 |
236 |
237 |
238 | ## Cocktail Sort
239 |
240 |
241 | 칵테일 정렬은 버블 정렬을 기반한 변형 된 알고리즘입니다. Cocktail shaker sort(칵테일 셰이커 정렬), bidirectional bubble sort(양방향 버블 정렬), cocktail sort(칵테일 정렬), shaker sort(셰이커 정렬) 이라고도 불립니다.
242 |
243 |
244 | ### COMPLEXITY
245 |
246 |
247 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
248 | | :-: | :-: | :-: | :-: | :-: | :-: |
249 | | ) | ) | ) | Yes | Yes | total : ), auxiliary : ) |
250 |
251 |
252 |
253 |
254 |
255 |
256 | ## Insertion Sort
257 |
258 |
259 | 삽입 정렬은 각 반복마다 배열의 앞에서부터 차례대로 이미 정렬된 배열 부분과 비교하여 자신의 위치를 찾아 삽입요소를 찾아 올바른 위치에 배치하게 됩니다.
260 |
261 |
262 | ### COMPLEXITY
263 |
264 |
265 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
266 | | :-: | :-: | :-: | :-: | :-: | :-: |
267 | | ) | ) | ) | Yes | Yes | total : ), auxiliary : ) |
268 |
269 |
270 |
271 |
272 |
273 |
274 | ## Selection Sort
275 |
276 |
277 | 선택 정렬은 정렬되지 않은 부분에서 각 반복을 통해 가장 작은 요소를 찾아 앞 위치에 배치하게 됩니다.
278 |
279 |
280 | ### COMPLEXITY
281 |
282 |
283 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
284 | | :-: | :-: | :-: | :-: | :-: | :-: |
285 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
286 |
287 |
288 |
289 |
290 |
291 |
292 | ## Shell Sort
293 |
294 |
295 | 셸 정렬은 삽입 정렬을 확장한 버전입니다. 먼저 일정 간격으로 서로 멀리 떨어져 있는 요소를 삽입 정렬해 나가면서 다음에는 그 사이의 간격을 줄여나가면서 정렬하게 됩니다.
296 |
297 |
298 |
299 |
300 | \*적용 된 Gap 시퀀스는 다음과 같습니다. [**Ciura sequence**](https://oeis.org/A102549)
301 |
302 |
303 | ### COMPLEXITY
304 |
305 |
306 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
307 | | :-: | :-: | :-: | :-: | :-: | :-: |
308 | | ) or ) | depends on gap sequence | ) or ) | Yes | No | total : ), auxiliary : ) |
309 |
310 |
311 |
312 |
313 |
314 |
315 | ## Merge Sort
316 |
317 |
318 |
319 | 병합 정렬은 **분할 정복 알고리즘**을 기반으로 합니다.
320 |
321 | 개념적으로 병합 정렬은 다음과 같이 작동합니다:
322 |
323 | 1. 정렬되지 않은 n개의 요소를 갖는 배열을 재귀적으로 최소 하나 이상의 요소를 포함하는 배열이 되도록 절반으로 나눕니다(요소가 한 개만 있는 배열은 정렬된 것으로 간주됩니다).
324 | 2. 분할 된 배열이 모두 합쳐질 때 까지 반복적으로 병합하여 정렬 합니다.
325 |
326 |
327 |
328 |
329 | 3가지 유형의 병합 정렬을 지원합니다.
330 | - **top-down**
331 | 하향식 병합 정렬 알고리즘은 분할 된 배열의 크기가 1이 될 때까지 배열을 재귀적으로 분할한 다음 해당 하위 배열들을 병합하여 정렬된 목록을 생성합니다.
332 | - **bottom-up**
333 | 상향식 병합 정렬 알고리즘은 크기가 1인 n개의 하위 배열을 두 버퍼 사이에서 앞 뒤로 하위 배열들을 반복적으로 병합합니다.
334 | - **parallel**
335 | 병렬 병합 정렬 알고리즘은 재귀 호출의 병렬화를 통해 하위 배열의 크기가 임계값보다 작아질 때까지 배열을 재귀적으로 분할한 다음 병합하는 하향식 정렬을 수행합니다. 이 때, 임계값보다 작은 하위 배열들은 상향식 정렬을 사용하여 정렬하게 됩니다.
336 |
337 |
338 |
339 |
340 | ### COMPLEXITY
341 |
342 |
343 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
344 | | :-: | :-: | :-: | :-: | :-: | :-: |
345 | | ) | ) | ) | No | Yes | total : ), auxiliary : ) |
346 |
347 |
348 |
349 |
350 |
351 |
352 | ## Heap Sort
353 |
354 |
355 | 힙 정렬은 배열을 힙의 원리처럼 배열에서 요소를 하나씩 제거한 다음 배열의 정렬된 부분에 삽입하여 정렬하게 됩니다.
356 |
357 |
358 | ### COMPLEXITY
359 |
360 |
361 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
362 | | :-: | :-: | :-: | :-: | :-: | :-: |
363 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
364 |
365 |
366 |
367 |
368 |
369 |
370 | ## Quick Sort
371 |
372 |
373 | 퀵 정렬은 배열에서 특정 피벗을 선택한 다음 피벗보다 작은지 큰지에 따라 다른 요소를 두 개의 하위 배열로 분할하게 되는 분할 정복 알고리즘을 기반으로 합니다. 재귀적으로 이 과정을 거쳐 정렬됩니다.
374 |
375 |
376 |
377 |
378 |
379 | 3가지 유형의 퀵 정렬을 지원합니다.
380 |
381 | - **left-pivot (+parallel)**
382 | 왼쪽 피벗 퀵 정렬은 왼쪽 요소를 피벗으로 선택하여 정렬합니다.
383 | - **middle-pivot (+parallel)**
384 | 중간 피벗 퀵 정렬은 중간 요소를 피벗으로 선택하여 정렬합니다.
385 | - **right-pivot (+parallel)**
386 | 오른쪽 피벗 퀵 정렬은 오른쪽 요소를 피벗으로 선택하여 정렬합니다.
387 |
388 | 또한 각 알고리즘은 재귀 호출의 병렬화도 지원합니다.
389 |
390 |
391 | ### COMPLEXITY
392 |
393 |
394 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
395 | | :-: | :-: | :-: | :-: | :-: | :-: |
396 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
397 |
398 |
399 |
400 |
401 |
402 |
403 | ## Dual-Pivot Quick Sort
404 |
405 |
406 | 이중 피벗 퀵 정렬은 Quick Sort를 기반으로 하지만, 배열에서 두 개의 요소를 피벗(pivot)으로 선택하여 정렬하는 방식에 차이가 있습니다.
407 | 정렬할 배열에서 두 개의 요소(피벗)를 선택하고 나머지 요소들을 작은 피벗(small pivot)보다 작은 요소, 피벗 사이에 있는 요소, 큰 피벗(big pivot)보다 큰 요소로 구분하여 배열을 분할하고 이러한 파티션을 재귀적인 과정을 통해 정렬하게 됩니다.
408 |
409 |
410 |
411 |
412 |
413 | 2가지 유형의 이중 피벗 퀵 정렬을 지원합니다.
414 |
415 | - **non-parallel**
416 | 정렬할 배열에서 두 개의 요소(피벗)를 선택하고 나머지 요소들을 작은 피벗(small pivot)보다 작은 요소, 피벗 사이에 있는 요소, 큰 피벗(big pivot)보다 큰 요소로 구분하여 배열을 분할하고 이러한 파티션을 재귀적인 과정을 통해 정렬하게 됩니다.
417 | - **parallel**
418 | 재귀 호출의 병렬화를 통해 각각의 정렬 알고리즘은 분할 된 배열의 크기가 임계값보다 작을 때까지 배열을 재귀적으로 분할한 배열을 병합하여 정렬하게 됩니다.
419 |
420 |
421 |
422 |
423 |
424 | ### COMPLEXITY
425 |
426 |
427 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
428 | | :-: | :-: | :-: | :-: | :-: | :-: |
429 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
430 |
431 |
432 |
433 |
434 |
435 |
436 | ## Binary Insertion Sort
437 |
438 |
439 | 이진 삽입 정렬은 삽입 정렬을 기반으로 한 확장 버전입니다. 이진 정렬이라고도 합니다.
440 | 이진 삽입 정렬은 이진 검색(Binary Search)을 사용하여 각 반복 과정에서 특정 요소를 삽입할 위치를 찾아 삽입하게 됩니다.
441 |
442 |
443 | ### COMPLEXITY
444 |
445 |
446 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
447 | | :-: | :-: | :-: | :-: | :-: | :-: |
448 | | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
449 |
450 |
451 |
452 |
453 |
454 |
455 | ## Tim Sort
456 |
457 |
458 |
459 | Timsort는 다양한 종류의 실제 데이터에서 잘 수행되도록 설계된 알고리즘으로, 병합 정렬과 삽입 정렬(또는 이진 삽입 정렬)에서 파생되어 혼합 된 **안정적인 하이브리드 정렬 알고리즘** 입니다. Python 프로그래밍 언어에서 사용하기 위해 2002년 Tim Peters에 의해 구현되었습니다.
460 |
461 |
462 | ### COMPLEXITY
463 |
464 |
465 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
466 | | :-: | :-: | :-: | :-: | :-: | :-: |
467 | | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
468 |
469 |
470 |
471 |
472 |
473 |
474 | ## Bitonic Sort
475 |
476 |
477 | 바이토닉 정렬은 병렬로 실행할 수 있는 비교 기반 정렬 알고리즘입니다. 무작위 숫자 시퀀스를 단조 증가했다가 감소하는 비트 시퀀스로 변환하는 데 중점을 둡니다. 병렬 환경에 최적화 되어있으며 GPU 병렬 처리로 사용되기도 하지만, 여기서는 기타 병렬화한 정렬 알고리즘들과 마찬가지로 GO 언어의 동시성 모델로 구현됩니다.
478 |
479 |
480 |
481 |
482 |
483 | 2가지 유형의 알고리즘을 지원합니다.
484 | - **non-parallel**
485 | 분할 된 배열의 크기가 1이 될 때까지 배열을 재귀적으로 분할한 다음 Bitonic Sequencing Rule에 따라 해당 하위 배열을 병합하여 정렬하게 됩니다.
486 | - **parallel**
487 | 재귀 호출의 병렬화를 통해 분할 된 배열의 크기가 임계값보다 작아질 때까지 배열을 재귀적으로 분할한 다음 비병렬화로 전환하여 Bitonic Sequencing Rule에 따라 하위 배열을 분할 및 병합하여 생성합니다.
488 |
489 |
490 |
491 | ### COMPLEXITY
492 |
493 |
494 | | Type | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
495 | | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
496 | | non-parallel | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
497 | | parallel | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
498 |
499 |
500 |
501 |
502 |
503 |
504 | ## Intro Sort
505 |
506 |
507 |
508 | 인트로 정렬은 최악의 경우에도 평균적으로 빠른 성능과 및 (점근적으로) 최적화 된 하이브리드 정렬 알고리즘입니다. 퀵정렬로 시작하여 재귀 깊이가 정렬되는 배열의 요소 개수에 따른 깊이 임계값(maximum depth: &space;\right&space;\rfloor) ) 수준을 초과하면 힙 정렬로 전환하고 분할 된 배열의 요소 개수가 길이 임계값(16) 미만이면 삽입 정렬로 전환합니다.
509 |
510 |
511 |
512 |
513 |
514 | 2가지 유형의 알고리즘을 지원합니다.
515 |
516 | - **non-parallel**
517 | 정렬할 배열에서 퀵 정렬을 사용할 때 요소(피벗)를 선택하고 선택 된 피벗을 제외한 다른 요소들이 피벗보다 작거나 큰지 여부에 따라 두 개의 하위 배열로 분할하고 재귀 깊이가 특정 임계값(maximum depth: &space;\right&space;\rfloor) )을 넘기 전까지 이러한 과정을 재귀적으로 거칩니다.
518 |
519 | - **parallel**
520 | 재귀 호출의 병렬화를 통해 각 병렬화 된 이중 피벗 퀵 정렬 알고리즘은 분할 된 배열의 크기가 임계값보다 작아지기 전까지 배열을 재귀적으로 분할하여 정렬합니다.
521 |
522 |
523 |
524 | ### COMPLEXITY
525 |
526 |
527 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
528 | | :-: | :-: | :-: | :-: | :-: | :-: |
529 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
530 |
531 |
532 |
533 |
534 |
535 |
536 | ## Cycle Sort
537 |
538 |
539 | 순환 정렬은 in-place 정렬이자 불안정 정렬 알고리즘으로, 배열에 대해 총 쓰기(write) 수의 관점에서 가장 적게 쓰기 위한 비교 정렬 알고리즘 입니다.
540 |
541 |
542 | ### COMPLEXITY
543 |
544 |
545 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
546 | | :-: | :-: | :-: | :-: | :-: | :-: |
547 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
548 |
549 |
550 |
551 |
552 |
553 |
554 | ## Odd-Even Sort
555 |
556 |
557 | 컴퓨팅 시스템 관점에서 홀짝 정렬은 원래 상호 로컬 연결의 병렬 프로세서에서 사용하기 위해 개발된 비교적 간단한 정렬 알고리즘입니다
558 |
559 |
560 |
561 | ### COMPLEXITY
562 |
563 |
564 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
565 | | :-: | :-: | :-: | :-: | :-: | :-: |
566 | | ) | ) | ) | Yes | Yes | total : ), auxiliary : ) |
567 |
568 |
569 |
570 |
571 |
572 |
573 | ## Odd-Even Merge Sort
574 |
575 |
576 |
577 | 홀짝 병합 정렬은 사이즈는
578 | ^2)) , 깊이는 ^2)) 를 갖는 네트워크 정렬을 위해 Ken Batcher 정렬 알고리즘 입니다.
579 |
580 |
581 |
582 |
583 | ### COMPLEXITY
584 |
585 |
586 | | Type | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
587 | | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
588 | | non-parallel | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
589 | | parallel | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
590 |
591 |
592 |
593 |
594 |
595 |
596 | ## Comb Sort
597 |
598 |
599 | 콤 정렬은 원래 1980년 Włodzimierz Dobosiewicz와 Artur Borowy가 설계한 비교적 간단한 정렬 알고리즘으로, 나중에 Stephen Lacey와 Richard Box가 1991년에 재발견(이 때 "Combsort"라고 이름을 지정)했습니다. Comb 정렬은 셸 정렬과 유사한 방식으로 버블 정렬을 개선하여 성능을 향상 시킨 정렬 알고리즘입니다.
600 |
601 |
602 | ### COMPLEXITY
603 |
604 |
605 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
606 | | :-: | :-: | :-: | :-: | :-: | :-: |
607 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
608 |
--------------------------------------------------------------------------------
/README-en.md:
--------------------------------------------------------------------------------
1 | **[한글 문서](./README.md)** | **English Document**
2 |
3 |
4 |
5 | 
6 | 
7 | 
8 | 
9 | 
10 |
11 | # GoSortingAlgorithms
12 |
13 |
14 |
15 | Various Sorting Algorithms with golang :octocat:
16 |
17 |
18 |
19 |
20 | ## :beginner: Installation
21 |
22 | Once you have installed Go, run the go get command to install the GoSoringAlgorithms package:
23 |
24 | ```shell
25 | $ go get github.com/kdgyun/GoSortingAlgorithms
26 | ```
27 |
28 |
29 |
30 |
31 | ## :book: Usage
32 |
33 | it's simple!
34 |
35 | ```go
36 |
37 | package main
38 |
39 | import (
40 | "github.com/kdgyun/GoSortingAlgorithms/sorts"
41 |
42 | crand "crypto/rand"
43 | "fmt"
44 | "math"
45 | "math/big"
46 | "math/rand"
47 | "sort"
48 | )
49 |
50 | // generate random data
51 | func SliceBuilder(len int) []int {
52 | seed, _ := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
53 | rand.Seed(seed.Int64())
54 |
55 | var slice []int
56 | for i := 0; i < len; i++ {
57 | slice = append(slice, rand.Int())
58 | }
59 | return slice
60 | }
61 |
62 | func main() {
63 | slice := SliceBuilder(1000000)
64 |
65 | sorts.QuickSort(slice) // sorts.____(slice []int)
66 |
67 | isSorted := sort.SliceIsSorted(slice, func(i, j int) bool {
68 | return slice[i] < slice[j]
69 | })
70 | fmt.Print(isSorted)
71 | }
72 |
73 | ```
74 |
75 |
76 |
77 |
78 |
79 | ## :test_tube: Simply Test
80 |
81 | It's easy to get test of all sorting algorithms with simplytest.
82 |
83 | ```go
84 |
85 | package main
86 |
87 | import (
88 | "github.com/kdgyun/GoSortingAlgorithms/simplytest"
89 | )
90 |
91 | func main() {
92 | simplytest.RunTest()
93 | }
94 |
95 |
96 | ```
97 |
98 |
99 |
100 |
101 | Example of Output
102 |
103 | ```
104 |
105 | +==================================================================================+
106 | | Random Test |
107 | +==================================================================================+
108 |
109 | ...
110 |
111 | [array length : 100000]
112 | make arrays...
113 | running bubble sort...
114 | running cocktail sort...
115 |
116 | ...
117 |
118 | running intro sort...
119 | running parallel intro sort...
120 | running cycle sort...
121 |
122 | +-------------------------------------------------------------------------------------------------+
123 | | name | ns | ms | verify | (err mag)
124 | |-------------------------------------------------------------------------------------------------|
125 | | bubble sort | 13016202738 ns | 13016 ms | true |
126 | |-------------------------------------------------------------------------------------------------|
127 | | cocktail sort | 8922656474 ns | 8922 ms | true |
128 | |-------------------------------------------------------------------------------------------------|
129 | | tim sort | 11419013 ns | 11 ms | true |
130 | |-------------------------------------------------------------------------------------------------|
131 | | bitonic sort | 32333072 ns | 32 ms | true |
132 | |-------------------------------------------------------------------------------------------------|
133 |
134 | ...
135 |
136 | |-------------------------------------------------------------------------------------------------|
137 | | intro sort | 6665792 ns | 6 ms | true |
138 | |-------------------------------------------------------------------------------------------------|
139 | | parallel intro sort | 2537508 ns | 2 ms | true |
140 | |-------------------------------------------------------------------------------------------------|
141 | | cycle sort | 20209957747 ns | 20209 ms | true |
142 | +-------------------------------------------------------------------------------------------------+
143 |
144 | ```
145 |
146 |
147 |
148 |
149 |
150 |
151 | ### Option
152 |
153 | There is an ```option.go``` file so that users can easily adjust the test, and you can adjust three major options in that file.
154 |
155 |
156 | 1. Select the sorting algorithm.
157 | If you want to test only a specific sorting algorithm or not, find the sorting name you want to change and change the variable to true or false. (True : enable, false : disable)
158 | > ex) SHELL_SORT Activate = false
159 |
160 | 2. Change the length of the slice to be tested.
161 | To change the length of the slice to be tested, configure the slice of the variable 'lengths' to the desired value.
162 | > ex) var lengths = [...]int{35, 50000, 100000}
163 |
164 |
165 | 3. You can activate or disable the data type of slice to be tested. Basically, all slices consisting of ascending, descending, and random data are tested. However, if you want to disable a specific data type, change the variable to false.
166 | > ex) ASCENDING_TEST Activate = false
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 | ## :mag_right: SUMMARY
176 |
177 | Algorithms covered so far:
178 |
179 | | name | function name |
180 | | --- | :-: |
181 | | [Bubble Sort](#bubble-sort) | BubbleSort |
182 | | [Cocktail Sort](#cocktail-sort) | CocktailSort |
183 | | [Insertion Sort](#insertion-sort) | InsertionSort |
184 | | [Selection Sort](#selection-sort) | SelectionSort |
185 | | [Shell Sort](#shell-sort) | ShellSort |
186 | | [Merge Sort (bottom-up)](#merge-sort) | BottomUpMergeSort |
187 | | [Merge Sort (top-down)](#merge-sort) | TopDownMergeSort |
188 | | [Merge Sort (parallel)](#merge-sort) | ParallelMergeSort |
189 | | [Heap Sort](#heap-sort) | HeapSort |
190 | | [Quick Sort (left-pivot)](#quick-sort) | QuickSortLP |
191 | | [Quick Sort (middle-pivot)](#quick-sort) | QuickSort |
192 | | [Quick Sort (left-pivot)](#quick-sort) | QuickSortRP |
193 | | [Quick Sort (left-pivot with parallel)](#quick-sort) | ParallelQuickSortLP |
194 | | [Quick Sort (middle-pivot with parallel)](#quick-sort) | ParallelQuickSort |
195 | | [Quick Sort (left-pivot with parallel)](#quick-sort) | ParallelQuickSortRP |
196 | | [Dual-pivot Quick Sort](#dual-pivot-quick-sort) | DualPivotQuickSort |
197 | | [Dual-pivot Quick Sort (parallel)](#dual-pivot-quick-sort) | ParallelDualPivotQuickSort |
198 | | [Binaray Insertion Sort](#binary-insertion-sort) | BinarySort |
199 | | [Tim Sort](#tim-sort) | TimSort |
200 | | [Bitonic Sort](#bitonic-sort) | BitonicSort |
201 | | [Bitonic Sort (parallel)](#bitonic-sort) | ParallelBitonicSort |
202 | | [Intro Sort](#intro-sort) | IntroSort |
203 | | [Intro Sort (parallel)](#intro-sort) | ParallelIntroSort |
204 | | [Cycle Sort](#cycle-sort) | CycleSort |
205 | | [Odd-Even Sort](#odd-even-sort) | OddEvenSort |
206 | | [Odd-Even Merge Sort](#odd-even-merge-sort) | OddEvenMergeSort |
207 | | [Odd-Even Merge Sort (parallel)](#odd-even-merge-sort) | ParallelOddEvenMergeSort |
208 | | [Comb Sort](#comb-sort) | CombSort |
209 |
210 |
211 |
212 |
213 |
214 | ## Bubble Sort
215 |
216 |
217 | Bubble sort repeatedly compares and swaps adjacent elements through the list.
218 |
219 | This implementation is optimized. so, if the slice(array) is sorted, exit the bubble sort method. If you don't want to optimize, delete the swapped variable in the bubbleSort method.
220 |
221 | ### COMPLEXITY
222 |
223 |
224 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
225 | | :-: | :-: | :-: | :-: | :-: | :-: |
226 | | ) | ) | ) or ) | Yes | Yes | total : ), auxiliary : ) |
227 |
228 |
229 |
230 |
231 |
232 |
233 | ## Cocktail Sort
234 |
235 |
236 | Cocktail Sort is a variation of Bubble sort.
237 | it is also known as Cocktail shaker sort, bidirectional bubble sort, cocktail sort, shaker sort.
238 |
239 |
240 | ### COMPLEXITY
241 |
242 |
243 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
244 | | :-: | :-: | :-: | :-: | :-: | :-: |
245 | | ) | ) | ) | Yes | Yes | total : ), auxiliary : ) |
246 |
247 |
248 |
249 |
250 |
251 |
252 | ## Insertion Sort
253 |
254 |
255 | Insertion sort is a method of finding element from the list through the iteration to place in the correct position.
256 |
257 |
258 | ### COMPLEXITY
259 |
260 |
261 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
262 | | :-: | :-: | :-: | :-: | :-: | :-: |
263 | | ) | ) | ) | Yes | Yes | total : ), auxiliary : ) |
264 |
265 |
266 |
267 |
268 |
269 |
270 | ## Selection Sort
271 |
272 |
273 | Selection sort is like finding minimum element from the unsorted part through each iteration to place it in front position.
274 |
275 |
276 | ### COMPLEXITY
277 |
278 |
279 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
280 | | :-: | :-: | :-: | :-: | :-: | :-: |
281 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
282 |
283 |
284 |
285 |
286 |
287 |
288 | ## Shell Sort
289 |
290 |
291 | Shell sort is an extended version of insertion sort. This algorithm first sorts the elements that are far away from each other, then it subsequently reduces the gap between them.
292 |
293 |
294 |
295 |
296 | \*The applied gap sequence is the [**Ciura sequence.**](https://oeis.org/A102549)
297 |
298 |
299 | ### COMPLEXITY
300 |
301 |
302 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
303 | | :-: | :-: | :-: | :-: | :-: | :-: |
304 | | ) or ) | depends on gap sequence | ) or ) | Yes | No | total : ), auxiliary : ) |
305 |
306 |
307 |
308 |
309 |
310 |
311 | ## Merge Sort
312 |
313 |
314 |
315 | Merge sort works on the basis of **Divide and Conquer algorithm.**
316 |
317 | Conceptually, a merge sort works as follows:
318 |
319 | 1. Divide the unsorted list into n sublists, each containing one element (a list of one element is considered sorted).
320 | 2. Repeatedly merge sublists to produce new sorted sublists until there is only one sublist remaining. This will be the sorted list.
321 |
322 |
323 |
324 |
325 | it supports 3 types of algorithms
326 | - **top-down**
327 | Top-down merge sort algorithm that recursively splits the list into sublists until sublist size is 1, then merges those sublists to produce a sorted list.
328 | - **bottom-up**
329 | Bottom-up merge sort algorithm which treats the slice(array) as an slice of n sublists of size 1, and iteratively merges sub-lists back and forth between two buffers
330 | - **parallel**
331 | Through parallelization of recursive calls, the parallel merge sorting algorithm recursively splits the list into sublists until the sublist size is smaller than the threshold, and then merges the sublists to create a sorted list.
332 | And sub-lists smaller than the threshold use a bottom-up list to produce a sorted list.
333 |
334 |
335 |
336 | ### COMPLEXITY
337 |
338 |
339 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
340 | | :-: | :-: | :-: | :-: | :-: | :-: |
341 | | ) | ) | ) | No | Yes | total : ), auxiliary : ) |
342 |
343 |
344 |
345 |
346 |
347 |
348 | ## Heap Sort
349 |
350 |
351 | Heap sort is to eliminate the elements one by one from the heap part of the list, and then insert them into the sorted part of the list.
352 |
353 |
354 | ### COMPLEXITY
355 |
356 |
357 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
358 | | :-: | :-: | :-: | :-: | :-: | :-: |
359 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
360 |
361 |
362 |
363 |
364 |
365 |
366 | ## Quick Sort
367 |
368 |
369 | Quick Sort is based on Divide-and-conquer algorithm where it selects a pivot element from the array and then partition the other elements into two sub-arrays according to whether they are less than or greater than the pivot. The sub-arrays are then sorted recursively.
370 |
371 |
372 |
373 |
374 | it supports 3 types of algorithms
375 |
376 | - **left-pivot (+parallel)**
377 | Left-pivot Quick sort is implemented with left element selected as the pivot
378 | - **middle-pivot (+parallel)**
379 | Middle-pivot Quick sort is implemented with middle element selected as the pivot
380 | - **right-pivot (+parallel)**
381 | right-pivot Quick sort is implemented with right element selected as the pivot
382 |
383 | Through parallelization of recursive calls, each parallel quick sorting algorithms recursively splits the list into sublists until the sublist size is smaller than the threshold, and then sorts the sublists that smaller than the threshold by use a basic quick sort to create a sorted list.
384 |
385 |
386 | ### COMPLEXITY
387 |
388 |
389 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
390 | | :-: | :-: | :-: | :-: | :-: | :-: |
391 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
392 |
393 |
394 |
395 |
396 |
397 |
398 | ## Dual-Pivot Quick Sort
399 |
400 |
401 | Dual-Pivot Quick Sort is based on Divide-and-conquer algorithm of quick sort, but there is a difference in selecting two elements (pivot) in the list to sort.
402 |
403 | Pick two elements(pivot) from the array to be sorted, partition the remaining elements into those less than the lesser pivot, those between the pivots, and those greater than the greater pivot, and recursively sort these partitions.
404 |
405 | it is also known as 3-way quick sort.
406 |
407 |
408 |
409 |
410 | it supports 2 types of algorithms
411 |
412 | - **non-parallel**
413 | Pick two elements(pivot) from the array to be sorted, partition the remaining elements into those less than the lesser pivot, those between the pivots, and those greater than the greater pivot, and recursively sort these partitions.
414 | - **parallel**
415 | Through parallelization of recursive calls, each parallel dual-pivot quick sorting algorithms recursively splits the list into sublists until the sublist size is smaller than the threshold, and then sorts the sublists that smaller than the threshold by use a basic dual-pivot quick sort to create a sorted list.
416 |
417 |
418 |
419 |
420 |
421 | ### COMPLEXITY
422 |
423 |
424 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
425 | | :-: | :-: | :-: | :-: | :-: | :-: |
426 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
427 |
428 |
429 |
430 |
431 |
432 |
433 | ## Binary Insertion Sort
434 |
435 |
436 | Binary Insertion Sort is an extended version of insertion sort. it also known as Binary Sort.
437 |
438 | Binary Insertion Sort uses binary search to find the proper location to insert the selected item at each iteration.
439 |
440 |
441 | ### COMPLEXITY
442 |
443 |
444 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
445 | | :-: | :-: | :-: | :-: | :-: | :-: |
446 | | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
447 |
448 |
449 |
450 |
451 |
452 |
453 | ## Tim Sort
454 |
455 |
456 |
457 | Timsort is a **hybrid stable sorting algorithm**, derived from merge sort and insertion sort(or binary insertion sort), designed to perform well on many kinds of real-world data. It was implemented by Tim Peters in 2002 for use in the Python programming language. The algorithm finds subsequences of the data that are already ordered (runs) and uses them to sort the remainder more efficiently.
458 |
459 |
460 | ### COMPLEXITY
461 |
462 |
463 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
464 | | :-: | :-: | :-: | :-: | :-: | :-: |
465 | | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
466 |
467 |
468 |
469 |
470 |
471 |
472 | ## Bitonic Sort
473 |
474 |
475 | Bitonic sort is a comparison-based sorting algorithm that can be run in parallel. It focuses on converting a random sequence of numbers into a bitonic sequence, one that monotonically increases, then decreases.
476 |
477 |
478 |
479 |
480 | it supports 2 types of algorithms
481 | - **non-parallel**
482 | non-parallel bitonic sort that recursively splits the list into sublists until sublist size is 1, then merges those sublists according to the Bitonic Sequencing Rule to produce a sorted list.
483 | - **parallel**
484 | Through parallelization of recursive calls, the parallel bitonic sorting algorithm recursively splits the list into sublists until the sublist size is smaller than the threshold, and then switches to non-parallelization to split and merge the sublists according to the Bitonic Sequencing Rule to create a sorted list.
485 |
486 |
487 |
488 | ### COMPLEXITY
489 |
490 |
491 | | Type | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
492 | | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
493 | | non-parallel | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
494 | | parallel | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
495 |
496 |
497 |
498 |
499 |
500 |
501 | ## Intro Sort
502 |
503 |
504 |
505 | Introsort is a hybrid sorting algorithm that provides both fast average performance and (asymptotically) optimal worst-case performance. It begins with quicksort, it switches to heapsort when the recursion depth exceeds a level based on
506 | (maximum depth:
507 | &space;\right&space;\rfloor)
508 | of)
509 | the number of elements being sorted and it switches to insertion sort when the number of elements is below some threshold(16).
510 |
511 |
512 |
513 |
514 |
515 | it supports 2 types of algorithms
516 |
517 | - **non-parallel**
518 | Pick a element(pivot) when uses quick sort from the array to be sorted, partition the other elements into two sub-arrays according to whether they are less than or greater than the pivot, and recursively sort these partitions until the recursion depth exceeds a level based on
519 | (maximum depth:
520 | &space;\right&space;\rfloor)
521 | of)
522 | the number of elements.
523 | - **parallel**
524 | Through parallelization of recursive calls, each parallel dual-pivot quick sorting algorithms recursively splits the list into sublists until the sublist size is smaller than the threshold, and then sorts the sublists that smaller than the threshold by use a basic dual-pivot quick sort to create a sorted list.
525 |
526 |
527 |
528 | ### COMPLEXITY
529 |
530 |
531 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
532 | | :-: | :-: | :-: | :-: | :-: | :-: |
533 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
534 |
535 |
536 |
537 |
538 |
539 |
540 | ## Cycle Sort
541 |
542 |
543 | Cycle sort is an in-place sorting Algorithm, unstable sorting algorithm, a comparison sort that is theoretically optimal in terms of the total number of writes to the original array.
544 |
545 |
546 | ### COMPLEXITY
547 |
548 |
549 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
550 | | :-: | :-: | :-: | :-: | :-: | :-: |
551 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
552 |
553 |
554 |
555 |
556 |
557 |
558 | ## Odd-Even Sort
559 |
560 |
561 | In computing, an odd–even sort or odd–even transposition sort (also known as brick sort or parity sort) is a relatively simple sorting algorithm, developed originally for use on parallel processors with local interconnections.
562 |
563 |
564 | ### COMPLEXITY
565 |
566 |
567 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
568 | | :-: | :-: | :-: | :-: | :-: | :-: |
569 | | ) | ) | ) | Yes | Yes | total : ), auxiliary : ) |
570 |
571 |
572 |
573 |
574 |
575 |
576 | ## Odd-Even Merge Sort
577 |
578 |
579 |
580 | odd–even mergesort is a generic construction devised by Ken Batcher for sorting networks of
581 | size
582 | ^2))
583 | and depth
584 | ^2))
585 | where n is the number of items to be sorted.
586 |
587 |
588 |
589 |
590 |
591 |
592 | ### COMPLEXITY
593 |
594 |
595 | | Type | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
596 | | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
597 | | non-parallel | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
598 | | parallel | ) | ) | ) | Yes | yes | total : ), auxiliary : ) |
599 |
600 |
601 |
602 |
603 |
604 |
605 | ## Comb Sort
606 |
607 |
608 | Comb sort is a relatively simple sorting algorithm originally designed by Włodzimierz Dobosiewicz and Artur Borowy in 1980, later rediscovered (and given the name "Combsort") by Stephen Lacey and Richard Box in 1991. Comb sort improves on bubble sort in the same way that Shellsort improves on insertion sort.
609 |
610 |
611 | ### COMPLEXITY
612 |
613 |
614 | | Worst-Case | Average-Case | Best-Case | in-place | stable | Space Complexity |
615 | | :-: | :-: | :-: | :-: | :-: | :-: |
616 | | ) | ) | ) | Yes | No | total : ), auxiliary : ) |
617 |
--------------------------------------------------------------------------------