diff --git a/README.md b/README.md index 06be382be..931f1af5c 100644 --- a/README.md +++ b/README.md @@ -867,24 +867,26 @@ Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. ##### Functions: 1. [`Bubble`](./sort/bubblesort.go#L9): Bubble is a simple generic definition of Bubble sort algorithm. -2. [`Comb`](./sort/combSort.go#L17): Comb is a simple sorting algorithm which is an improvement of the bubble sorting algorithm. -3. [`Count`](./sort/countingsort.go#L11): No description provided. -4. [`Exchange`](./sort/exchangesort.go#L8): No description provided. -5. [`HeapSort`](./sort/heapsort.go#L116): No description provided. -6. [`ImprovedSimple`](./sort/simplesort.go#L27): ImprovedSimple is a improve SimpleSort by skipping an unnecessary comparison of the first and last. This improved version is more similar to implementation of insertion sort -7. [`Insertion`](./sort/insertionsort.go#L5): No description provided. -8. [`Merge`](./sort/mergesort.go#L41): Merge Perform merge sort on a slice -9. [`MergeIter`](./sort/mergesort.go#L55): No description provided. -10. [`ParallelMerge`](./sort/mergesort.go#L66): ParallelMerge Perform merge sort on a slice using goroutines -11. [`Partition`](./sort/quicksort.go#L12): No description provided. -12. [`Patience`](./sort/patiencesort.go#L13): No description provided. -13. [`Pigeonhole`](./sort/pigeonholesort.go#L15): Pigeonhole sorts a slice using pigeonhole sorting algorithm. NOTE: To maintain time complexity O(n + N), this is the reason for having only Integer constraint instead of Ordered. -14. [`Quicksort`](./sort/quicksort.go#L39): Quicksort Sorts the entire array -15. [`QuicksortRange`](./sort/quicksort.go#L26): QuicksortRange Sorts the specified range within the array -16. [`RadixSort`](./sort/radixsort.go#L43): No description provided. -17. [`Selection`](./sort/selectionsort.go#L5): No description provided. -18. [`Shell`](./sort/shellsort.go#L5): No description provided. -19. [`Simple`](./sort/simplesort.go#L13): No description provided. +2. [`Bucket Sort`](./sort/bucketsort.go#L5): Bucket Sort works with the idea of distributing the elements of an array into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. +3. [`Comb`](./sort/combSort.go#L17): Comb is a simple sorting algorithm which is an improvement of the bubble sorting algorithm. +4. [`Count`](./sort/countingsort.go#L11): No description provided. +5. [`Exchange`](./sort/exchangesort.go#L8): No description provided. +6. [`HeapSort`](./sort/heapsort.go#L116): No description provided. +7. [`ImprovedSimple`](./sort/simplesort.go#L27): ImprovedSimple is a improve SimpleSort by skipping an unnecessary comparison of the first and last. This improved version is more similar to implementation of insertion sort +8. [`Insertion`](./sort/insertionsort.go#L5): No description provided. +9. [`Merge`](./sort/mergesort.go#L41): Merge Perform merge sort on a slice +10. [`MergeIter`](./sort/mergesort.go#L55): No description provided. +11. [`Pancake Sort`](./sort/pancakesort.go#L7): Pancake Sort is a sorting algorithm that is similar to selection sort that reverses elements of an array. The Pancake Sort uses the flip operation to sort the array. +12. [`ParallelMerge`](./sort/mergesort.go#L66): ParallelMerge Perform merge sort on a slice using goroutines +13. [`Partition`](./sort/quicksort.go#L12): No description provided. +14. [`Patience`](./sort/patiencesort.go#L13): No description provided. +15. [`Pigeonhole`](./sort/pigeonholesort.go#L15): Pigeonhole sorts a slice using pigeonhole sorting algorithm. NOTE: To maintain time complexity O(n + N), this is the reason for having only Integer constraint instead of Ordered. +16. [`Quicksort`](./sort/quicksort.go#L39): Quicksort Sorts the entire array +17. [`QuicksortRange`](./sort/quicksort.go#L26): QuicksortRange Sorts the specified range within the array +18. [`RadixSort`](./sort/radixsort.go#L43): No description provided. +19. [`Selection`](./sort/selectionsort.go#L5): No description provided. +20. [`Shell`](./sort/shellsort.go#L5): No description provided. +21. [`Simple`](./sort/simplesort.go#L13): No description provided. --- ##### Types diff --git a/sort/bucketsort.go b/sort/bucketsort.go new file mode 100644 index 000000000..3f05a41a4 --- /dev/null +++ b/sort/bucketsort.go @@ -0,0 +1,46 @@ +package sort + +import "github.com/TheAlgorithms/Go/constraints" + +// Bucket sorts a slice. It is mainly useful +// when input is uniformly distributed over a range. +func Bucket[T constraints.Number](arr []T) []T { + // early return if the array too small + if len(arr) <= 1 { + return arr + } + + // find the maximum and minimum elements in arr + max := arr[0] + min := arr[0] + for _, v := range arr { + if v > max { + max = v + } + if v < min { + min = v + } + } + + // create an empty bucket for each element in arr + bucket := make([][]T, len(arr)) + + // put each element in the appropriate bucket + for _, v := range arr { + bucketIndex := int((v - min) / (max - min) * T(len(arr)-1)) + bucket[bucketIndex] = append(bucket[bucketIndex], v) + } + + // use insertion sort to sort each bucket + for i := range bucket { + bucket[i] = Insertion(bucket[i]) + } + + // concatenate the sorted buckets + sorted := make([]T, 0, len(arr)) + for _, v := range bucket { + sorted = append(sorted, v...) + } + + return sorted +} diff --git a/sort/pancakesort.go b/sort/pancakesort.go new file mode 100644 index 000000000..a809ba1c4 --- /dev/null +++ b/sort/pancakesort.go @@ -0,0 +1,44 @@ +package sort + +import "github.com/TheAlgorithms/Go/constraints" + +// Pancake sorts a slice using flip operations, +// where flip refers to the idea of reversing the +// slice from index `0` to `i`. +func Pancake[T constraints.Ordered](arr []T) []T { + // early return if the array too small + if len(arr) <= 1 { + return arr + } + + // start from the end of the array + for i := len(arr) - 1; i > 0; i-- { + // find the index of the maximum element in arr + max := 0 + for j := 1; j <= i; j++ { + if arr[j] > arr[max] { + max = j + } + } + + // if the maximum element is not at the end of the array + if max != i { + // flip the maximum element to the beginning of the array + arr = flip(arr, max) + + // flip the maximum element to the end of the array by flipping the whole array + arr = flip(arr, i) + } + } + + return arr +} + +// flip reverses the input slice from `0` to `i`. +func flip[T constraints.Ordered](arr []T, i int) []T { + for j := 0; j < i; j++ { + arr[j], arr[i] = arr[i], arr[j] + i-- + } + return arr +} diff --git a/sort/sorts_test.go b/sort/sorts_test.go index ecee3d33c..9f34a23cb 100644 --- a/sort/sorts_test.go +++ b/sort/sorts_test.go @@ -81,6 +81,10 @@ func TestBubble(t *testing.T) { testFramework(t, sort.Bubble[int]) } +func TestBucketSort(t *testing.T) { + testFramework(t, sort.Bucket[int]) +} + func TestExchange(t *testing.T) { testFramework(t, sort.Exchange[int]) } @@ -153,6 +157,10 @@ func TestComb(t *testing.T) { testFramework(t, sort.Comb[int]) } +func TestPancakeSort(t *testing.T) { + testFramework(t, sort.Pancake[int]) +} + func TestPigeonhole(t *testing.T) { testFramework(t, sort.Pigeonhole[int]) } @@ -206,6 +214,10 @@ func BenchmarkBubble(b *testing.B) { benchmarkFramework(b, sort.Bubble[int]) } +func BenchmarkBucketSort(b *testing.B) { + benchmarkFramework(b, sort.Bucket[int]) +} + func BenchmarkExchange(b *testing.B) { benchmarkFramework(b, sort.Exchange[int]) } @@ -263,6 +275,10 @@ func BenchmarkComb(b *testing.B) { benchmarkFramework(b, sort.Comb[int]) } +func BenchmarkPancakeSort(b *testing.B) { + benchmarkFramework(b, sort.Pancake[int]) +} + func BenchmarkPigeonhole(b *testing.B) { benchmarkFramework(b, sort.Pigeonhole[int]) }