Skip to content

Commit

Permalink
feat: add cycle sort algorithm (#634)
Browse files Browse the repository at this point in the history
* feat: add cycle sort algorithm

* feat: add cycle sort algorithm

* feat: address code review comments

* feat: address code review comments

* Remove unnecessary newline

---------

Co-authored-by: Taj <[email protected]>
  • Loading branch information
PalAditya and tjgurwara99 authored May 1, 2023
1 parent a0bc6d6 commit 0de898f
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
58 changes: 58 additions & 0 deletions sort/cyclesort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package sort

import (
"github.com/TheAlgorithms/Go/constraints"
)

// Cycle sort is an in-place, unstable sorting algorithm that is particularly useful
// when sorting arrays containing elements with a small range of values. It is theoretically
// optimal in terms of the total number of writes to the original array.
func Cycle[T constraints.Number](arr []T) []T {
counter, cycle, len := 0, 0, len(arr)
// Early return if the array too small
if len <= 1 {
return arr
}

for cycle = 0; cycle < len-1; cycle++ {
elem := arr[cycle]
// Find total smaller elements to right
pos := cycle
for counter = cycle + 1; counter < len; counter++ {
if arr[counter] < elem {
pos++
}
}
// In case this element is already in correct position, let's skip processing
if pos == cycle {
continue
}
// In case we have same elements, we want to skip to the end of that list as well, ignoring order
// This makes the algorithm unstable for composite elements
for elem == arr[pos] {
pos++
}
// Now let us put the item to it's right position
arr[pos], elem = elem, arr[pos]

//We need to rotate the array till we have reached the start of the cycle again
for pos != cycle {
pos = cycle
// Find smaller elements to right again
for counter = cycle + 1; counter < len; counter++ {
if arr[counter] < elem {
pos++
}
}
for elem == arr[pos] {
pos++
}
//We can do this unconditionally, but the check helps prevent redundant writes to the array
if elem != arr[pos] {
arr[pos], elem = elem, arr[pos]
}
}
}

return arr
}
8 changes: 8 additions & 0 deletions sort/sorts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ func TestPatience(t *testing.T) {
testFramework(t, sort.Patience[int])
}

func TestCycle(t *testing.T) {
testFramework(t, sort.Cycle[int])
}

//END TESTS

func benchmarkFramework(b *testing.B, f func(arr []int) []int) {
Expand Down Expand Up @@ -286,3 +290,7 @@ func BenchmarkPigeonhole(b *testing.B) {
func BenchmarkPatience(b *testing.B) {
benchmarkFramework(b, sort.Patience[int])
}

func BenchmarkCycle(b *testing.B) {
benchmarkFramework(b, sort.Cycle[int])
}

0 comments on commit 0de898f

Please sign in to comment.