├── 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 | ![](https://img.shields.io/github/go-mod/go-version/kdgyun/GoSortingAlgorithms/main) 6 | ![](https://img.shields.io/github/issues/kdgyun/GoSortingAlgorithms) 7 | ![](https://img.shields.io/github/commit-status/kdgyun/GoSortingAlgorithms/main/ee331ab723bf79aa3b98a2c4e143bd07eee5b1f2) 8 | ![](https://img.shields.io/github/repo-size/kdgyun/GoSortingAlgorithms) 9 | ![](https://github.com/kdgyun/GoSortingAlgorithms/actions/workflows/go.yml/badge.svg?branch=main) 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) or ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) or ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | depends on gap sequence | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) or ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | No | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | 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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(log_n)](https://latex.codecogs.com/svg.image?O(\log&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(log_n)](https://latex.codecogs.com/svg.image?O(\log&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | 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 | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | No | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 497 | | parallel | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | Yes | No | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 498 | 499 | 500 | 501 |
502 |
503 | 504 | ## Intro Sort 505 | 506 |
507 | 508 | 인트로 정렬은 최악의 경우에도 평균적으로 빠른 성능과 및 (점근적으로) 최적화 된 하이브리드 정렬 알고리즘입니다. 퀵정렬로 시작하여 재귀 깊이가 정렬되는 배열의 요소 개수에 따른 깊이 임계값(maximum depth: ![2ceil(log2_n)](https://latex.codecogs.com/svg.image?2&space;&space;\left&space;\lfloor&space;\log_2(n)&space;\right&space;\rfloor) ) 수준을 초과하면 힙 정렬로 전환하고 분할 된 배열의 요소 개수가 길이 임계값(16) 미만이면 삽입 정렬로 전환합니다. 509 | 510 |
511 |
512 | 513 | 514 | 2가지 유형의 알고리즘을 지원합니다. 515 | 516 | - **non-parallel** 517 | 정렬할 배열에서 퀵 정렬을 사용할 때 요소(피벗)를 선택하고 선택 된 피벗을 제외한 다른 요소들이 피벗보다 작거나 큰지 여부에 따라 두 개의 하위 배열로 분할하고 재귀 깊이가 특정 임계값(maximum depth: ![2ceil(log2_n)](https://latex.codecogs.com/svg.image?2&space;&space;\left&space;\lfloor&space;\log_2(n)&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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(log_n)](https://latex.codecogs.com/svg.image?O(\log&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 567 | 568 | 569 | 570 |
571 |
572 | 573 | ## Odd-Even Merge Sort 574 | 575 |
576 | 577 | 홀짝 병합 정렬은 사이즈는 578 | ![O(n(log_n)^2)](https://latex.codecogs.com/svg.image?O(n(\log&space;n)^2)) , 깊이는 ![O((log_n)^2)](https://latex.codecogs.com/svg.image?O((\log&space;n)^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 | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | yes | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 589 | | parallel | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | Yes | yes | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2/p^2)](https://latex.codecogs.com/svg.image?O(n^{2}/2^{p})) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 608 | -------------------------------------------------------------------------------- /README-en.md: -------------------------------------------------------------------------------- 1 | **[한글 문서](./README.md)** | **English Document** 2 | 3 |
4 | 5 | ![](https://img.shields.io/github/go-mod/go-version/kdgyun/GoSortingAlgorithms/main) 6 | ![](https://img.shields.io/github/issues/kdgyun/GoSortingAlgorithms) 7 | ![](https://img.shields.io/github/commit-status/kdgyun/GoSortingAlgorithms/main/ee331ab723bf79aa3b98a2c4e143bd07eee5b1f2) 8 | ![](https://img.shields.io/github/repo-size/kdgyun/GoSortingAlgorithms) 9 | ![](https://github.com/kdgyun/GoSortingAlgorithms/actions/workflows/go.yml/badge.svg?branch=main) 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) or ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) or ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | depends on gap sequence | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) or ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | No | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | 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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(log_n)](https://latex.codecogs.com/svg.image?O(\log&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(log_n)](https://latex.codecogs.com/svg.image?O(\log&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | Yes | yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(n)](https://latex.codecogs.com/svg.image?O(n)) | 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 | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | No | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 494 | | parallel | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | Yes | No | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 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 | ![2ceil(log2_n)](https://latex.codecogs.com/svg.image?2&space;&space;\left&space;\lfloor&space;\log_2(n)&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 | ![2ceil(log2_n)](https://latex.codecogs.com/svg.image?2&space;&space;\left&space;\lfloor&space;\log_2(n)&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 | | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(log_n)](https://latex.codecogs.com/svg.image?O(\log&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n)) | Yes | Yes | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 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 | ![O(n(log_n)^2)](https://latex.codecogs.com/svg.image?O(n(\log&space;n)^2)) 583 | and depth 584 | ![O((log_n)^2)](https://latex.codecogs.com/svg.image?O((\log&space;n)^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 | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | Yes | yes | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 598 | | parallel | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | ![O(log^2_n)](https://latex.codecogs.com/svg.image?O(\log^2&space;n)) | Yes | yes | total : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)), auxiliary : ![O(nlog^2_n)](https://latex.codecogs.com/svg.image?O(n\log^2&space;n)) | 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 | | ![O(n^2)](https://latex.codecogs.com/svg.image?O(n^{2})) | ![O(n^2/p^2)](https://latex.codecogs.com/svg.image?O(n^{2}/2^{p})) | ![O(nlog_n)](https://latex.codecogs.com/svg.image?O(n\log&space;n)) | Yes | No | total : ![O(n)](https://latex.codecogs.com/svg.image?O(n)), auxiliary : ![O(1)](https://latex.codecogs.com/svg.image?O(1)) | 617 | --------------------------------------------------------------------------------