diff --git a/src/algorithms/sorting/comb-sort/CombSort.js b/src/algorithms/sorting/comb-sort/CombSort.js new file mode 100644 index 0000000000..74b590406b --- /dev/null +++ b/src/algorithms/sorting/comb-sort/CombSort.js @@ -0,0 +1,48 @@ +import Sort from '../Sort'; + +export default class CombSort extends Sort { + sort(originalArray) { + // Clone original array to prevent its modification. + const array = [...originalArray]; + + // Gap sequence shrink factor (empirically found to be ~1.3) + const shrinkFactor = 1.3; + + // Initialize gap as array length + let gap = array.length; + + // Initialize swapped as true to enter the loop + let swapped = true; + + // Keep iterating while gap is greater than 1 or there was a swap + while (gap > 1 || swapped) { + // Update gap using shrink factor + gap = Math.floor(gap / shrinkFactor); + + // Ensure gap is at least 1 + if (gap < 1) { + gap = 1; + } + + // Reset swapped flag + swapped = false; + + // Compare elements with current gap + for (let i = 0; i + gap < array.length; i += 1) { + // Call visiting callback. + this.callbacks.visitingCallback(array[i]); + + // Compare elements at distance of gap + if (this.comparator.lessThan(array[i + gap], array[i])) { + // Swap elements + [array[i], array[i + gap]] = [array[i + gap], array[i]]; + + // Mark that a swap occurred + swapped = true; + } + } + } + + return array; + } +} diff --git a/src/algorithms/sorting/comb-sort/README.md b/src/algorithms/sorting/comb-sort/README.md new file mode 100644 index 0000000000..d7aef61ab1 --- /dev/null +++ b/src/algorithms/sorting/comb-sort/README.md @@ -0,0 +1,27 @@ +# Comb Sort + +_Read this in other languages:_ +[_português_](README.pt-BR.md) + +## Description + +Comb Sort improves on Bubble Sort by using a gap larger than 1. +The gap starts at the length of the list and shrinks by a factor +of 1.3 each iteration until it reaches 1. At that point, Comb Sort +becomes equivalent to Bubble Sort, but by that time most of the +work has been done and the list is nearly sorted. + +The shrink factor of 1.3 has been empirically shown to be the best +value for the shrink factor for Comb Sort. + +## Complexity + +| Name | Best | Average | Worst | Memory | Stable | +| ----------------- | --------- | -------------- | --------------- | ------- | ------ | +| Comb sort | n log(n) | n²/2ᵈ (n log²n) | n² | 1 | No | + +## References + +- [Wikipedia](https://en.wikipedia.org/wiki/Comb_sort) +- [GeeksForGeeks](https://www.geeksforgeeks.org/comb-sort/) +- [YouTube](https://www.youtube.com/watch?v=J4_1A6lxfFQ) diff --git a/src/algorithms/sorting/comb-sort/__test__/CombSort.test.js b/src/algorithms/sorting/comb-sort/__test__/CombSort.test.js new file mode 100644 index 0000000000..4570686317 --- /dev/null +++ b/src/algorithms/sorting/comb-sort/__test__/CombSort.test.js @@ -0,0 +1,38 @@ +import CombSort from '../CombSort'; +import { + equalArr, + notSortedArr, + reverseArr, + sortedArr, + SortTester, +} from '../../SortTester'; + +describe('CombSort', () => { + it('should sort array', () => { + SortTester.testSort(CombSort); + }); + + it('should sort array with custom comparator', () => { + SortTester.testSortWithCustomComparator(CombSort); + }); + + it('should sort negative numbers', () => { + SortTester.testNegativeNumbersSort(CombSort); + }); + + it('should visit SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + CombSort, + sortedArr, + 10, + ); + }); + + it('should visit NOT SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + CombSort, + notSortedArr, + 30, + ); + }); +});