mirror of
https://github.com/trekhleb/javascript-algorithms.git
synced 2025-07-06 01:15:56 +08:00
Add selection sort.
This commit is contained in:
@ -11,7 +11,6 @@ export class SortTester {
|
||||
expect(sorter.sort([1])).toEqual([1]);
|
||||
expect(sorter.sort([1, 2])).toEqual([1, 2]);
|
||||
expect(sorter.sort([2, 1])).toEqual([1, 2]);
|
||||
expect(sorter.sort([1, 1, 1])).toEqual([1, 1, 1]);
|
||||
expect(sorter.sort(sortedArr)).toEqual(sortedArr);
|
||||
expect(sorter.sort(reverseArr)).toEqual(sortedArr);
|
||||
expect(sorter.sort(notSortedArr)).toEqual(sortedArr);
|
||||
@ -33,6 +32,21 @@ export class SortTester {
|
||||
expect(sorter.sort([''])).toEqual(['']);
|
||||
expect(sorter.sort(['a'])).toEqual(['a']);
|
||||
expect(sorter.sort(['aa', 'a'])).toEqual(['a', 'aa']);
|
||||
expect(sorter.sort(['aa', 'aa'])).toEqual(['aa', 'aa']);
|
||||
}
|
||||
|
||||
static testSortStability(SortingClass) {
|
||||
const callbacks = {
|
||||
compareCallback: (a, b) => {
|
||||
if (a.length === b.length) {
|
||||
return 0;
|
||||
}
|
||||
return a.length < b.length ? -1 : 1;
|
||||
},
|
||||
};
|
||||
|
||||
const sorter = new SortingClass(callbacks);
|
||||
|
||||
expect(sorter.sort(['bb', 'aa', 'c'])).toEqual(['c', 'bb', 'aa']);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import Sort from '../Sort';
|
||||
|
||||
export default class BubbleSort extends Sort {
|
||||
sort(initialArray) {
|
||||
sort(originalArray) {
|
||||
// Flag that holds info about whether the swap has occur or not.
|
||||
let swapped = false;
|
||||
// Clone original array to prevent its modification.
|
||||
const array = initialArray.slice(0);
|
||||
const array = originalArray.slice(0);
|
||||
|
||||
for (let i = 0; i < array.length; i += 1) {
|
||||
swapped = false;
|
||||
|
@ -16,6 +16,10 @@ describe('BubbleSort', () => {
|
||||
SortTester.testSortWithCustomComparator(BubbleSort);
|
||||
});
|
||||
|
||||
it('should do stable sorting', () => {
|
||||
SortTester.testSortStability(BubbleSort);
|
||||
});
|
||||
|
||||
it('should visit EQUAL array element specified number of times', () => {
|
||||
const expectedNumberOfVisits = 19;
|
||||
|
||||
|
12
src/algorithms/sorting/selection-sort/README.md
Normal file
12
src/algorithms/sorting/selection-sort/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Selection Sort
|
||||
|
||||
Selection sort is a sorting algorithm, specifically an
|
||||
in-place comparison sort. It has O(n2) time complexity,
|
||||
making it inefficient on large lists, and generally
|
||||
performs worse than the similar insertion sort.
|
||||
Selection sort is noted for its simplicity, and it has
|
||||
performance advantages over more complicated algorithms
|
||||
in certain situations, particularly where auxiliary
|
||||
memory is limited.
|
||||
|
||||

|
31
src/algorithms/sorting/selection-sort/SelectionSort.js
Normal file
31
src/algorithms/sorting/selection-sort/SelectionSort.js
Normal file
@ -0,0 +1,31 @@
|
||||
import Sort from '../Sort';
|
||||
|
||||
export default class SelectionSort extends Sort {
|
||||
sort(originalArray) {
|
||||
// Clone original array to prevent its modification.
|
||||
const array = originalArray.slice(0);
|
||||
|
||||
for (let i = 0; i < array.length - 1; i += 1) {
|
||||
let minIndex = i;
|
||||
|
||||
// Find minimum element in the rest of array.
|
||||
for (let j = i + 1; j < array.length; j += 1) {
|
||||
// Call visiting callback.
|
||||
this.callbacks.visitingCallback(array[j]);
|
||||
|
||||
if (this.comparator.lessThen(array[j], array[minIndex])) {
|
||||
minIndex = j;
|
||||
}
|
||||
}
|
||||
|
||||
// If new minimum element has been found then swap it with current i-th element.
|
||||
if (minIndex !== i) {
|
||||
const tmp = array[i];
|
||||
array[i] = array[minIndex];
|
||||
array[minIndex] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
import SelectionSort from '../SelectionSort';
|
||||
import {
|
||||
equalArr,
|
||||
notSortedArr,
|
||||
reverseArr,
|
||||
sortedArr,
|
||||
SortTester,
|
||||
} from '../../SortTester';
|
||||
|
||||
describe('SelectionSort', () => {
|
||||
it('should sort array', () => {
|
||||
SortTester.testSort(SelectionSort);
|
||||
});
|
||||
|
||||
it('should sort array with custom comparator', () => {
|
||||
SortTester.testSortWithCustomComparator(SelectionSort);
|
||||
});
|
||||
|
||||
it('should visit EQUAL array element specified number of times', () => {
|
||||
const expectedNumberOfVisits = 190;
|
||||
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
SelectionSort,
|
||||
equalArr,
|
||||
expectedNumberOfVisits,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit SORTED array element specified number of times', () => {
|
||||
const expectedNumberOfVisits = 190;
|
||||
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
SelectionSort,
|
||||
sortedArr,
|
||||
expectedNumberOfVisits,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit NOT SORTED array element specified number of times', () => {
|
||||
const expectedNumberOfVisits = 190;
|
||||
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
SelectionSort,
|
||||
notSortedArr,
|
||||
expectedNumberOfVisits,
|
||||
);
|
||||
});
|
||||
|
||||
it('should visit REVERSE SORTED array element specified number of times', () => {
|
||||
const expectedNumberOfVisits = 190;
|
||||
|
||||
SortTester.testAlgorithmTimeComplexity(
|
||||
SelectionSort,
|
||||
reverseArr,
|
||||
expectedNumberOfVisits,
|
||||
);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user