mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-11-13 06:23:00 +08:00
Add quick sort.
This commit is contained in:
parent
250d90af3c
commit
c7110be47e
20
README.md
20
README.md
@ -36,7 +36,8 @@
|
|||||||
* [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort)
|
* [Insertion Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/insertion-sort)
|
||||||
* [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort)
|
* [Heap Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/heap-sort)
|
||||||
* [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort)
|
* [Merge Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/merge-sort)
|
||||||
* [Quick Sort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort)
|
* [Quicksort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/quick-sort)
|
||||||
|
* [Shellsort](https://github.com/trekhleb/javascript-algorithms/tree/master/src/algorithms/sorting/shell-sort)
|
||||||
|
|
||||||
## Running Tests
|
## Running Tests
|
||||||
|
|
||||||
@ -106,11 +107,12 @@ Below is the list of some of the most used Big O notations and their performance
|
|||||||
|
|
||||||
### Array Sorting Algorithms Complexity
|
### Array Sorting Algorithms Complexity
|
||||||
|
|
||||||
| Name | Best | Average | Worst | Memory | Stable |
|
| Name | Best | Average | Worst | Memory | Stable |
|
||||||
| --------------------- | :-------: | :-------: | :-------: | :-------: | :-------: |
|
| --------------------- | :-------: | :-------: | :-----------: | :-------: | :-------: |
|
||||||
| **Bubble sort** | n | n^2 | n^2 | 1 | Yes |
|
| **Bubble sort** | n | n^2 | n^2 | 1 | Yes |
|
||||||
| **Insertion sort** | n | n^2 | n^2 | 1 | Yes |
|
| **Insertion sort** | n | n^2 | n^2 | 1 | Yes |
|
||||||
| **Selection sort** | n^2 | n^2 | n^2 | 1 | No |
|
| **Selection sort** | n^2 | n^2 | n^2 | 1 | No |
|
||||||
| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No |
|
| **Heap sort** | n log(n) | n log(n) | n log(n) | 1 | No |
|
||||||
| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes |
|
| **Merge sort** | n log(n) | n log(n) | n log(n) | n | Yes |
|
||||||
| **Quick sort** | n log(n) | n log(n) | n^2 | log(n) | No |
|
| **Quick sort** | n log(n) | n log(n) | n^2 | log(n) | No |
|
||||||
|
| **Shell sort** | n log(n) | depends on gap sequence | n (log(n))^2 | 1 | No |
|
||||||
|
@ -32,7 +32,7 @@ export class SortTester {
|
|||||||
expect(sorter.sort([''])).toEqual(['']);
|
expect(sorter.sort([''])).toEqual(['']);
|
||||||
expect(sorter.sort(['a'])).toEqual(['a']);
|
expect(sorter.sort(['a'])).toEqual(['a']);
|
||||||
expect(sorter.sort(['aa', 'a'])).toEqual(['a', 'aa']);
|
expect(sorter.sort(['aa', 'a'])).toEqual(['a', 'aa']);
|
||||||
expect(sorter.sort(['aa', 'q', 'a', 'bbbb', 'ccc'])).toEqual(['q', 'a', 'aa', 'ccc', 'bbbb']);
|
expect(sorter.sort(['aa', 'q', 'bbbb', 'ccc'])).toEqual(['q', 'aa', 'ccc', 'bbbb']);
|
||||||
expect(sorter.sort(['aa', 'aa'])).toEqual(['aa', 'aa']);
|
expect(sorter.sort(['aa', 'aa'])).toEqual(['aa', 'aa']);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +49,7 @@ export class SortTester {
|
|||||||
const sorter = new SortingClass(callbacks);
|
const sorter = new SortingClass(callbacks);
|
||||||
|
|
||||||
expect(sorter.sort(['bb', 'aa', 'c'])).toEqual(['c', 'bb', 'aa']);
|
expect(sorter.sort(['bb', 'aa', 'c'])).toEqual(['c', 'bb', 'aa']);
|
||||||
|
expect(sorter.sort(['aa', 'q', 'a', 'bbbb', 'ccc'])).toEqual(['q', 'a', 'aa', 'ccc', 'bbbb']);
|
||||||
}
|
}
|
||||||
|
|
||||||
static testAlgorithmTimeComplexity(SortingClass, arrayToBeSorted, numberOfVisits) {
|
static testAlgorithmTimeComplexity(SortingClass, arrayToBeSorted, numberOfVisits) {
|
||||||
|
48
src/algorithms/sorting/shell-sort/README.md
Normal file
48
src/algorithms/sorting/shell-sort/README.md
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Shellsort
|
||||||
|
|
||||||
|
Shellsort, also known as Shell sort or Shell's method,
|
||||||
|
is an in-place comparison sort. It can be seen as either a
|
||||||
|
generalization of sorting by exchange (bubble sort) or sorting
|
||||||
|
by insertion (insertion sort). The method starts by sorting
|
||||||
|
pairs of elements far apart from each other, then progressively
|
||||||
|
reducing the gap between elements to be compared. Starting
|
||||||
|
with far apart elements, it can move some out-of-place
|
||||||
|
elements into position faster than a simple nearest neighbor
|
||||||
|
exchange
|
||||||
|
|
||||||
|
![Shellsort](https://upload.wikimedia.org/wikipedia/commons/d/d8/Sorting_shellsort_anim.gif)
|
||||||
|
|
||||||
|
## How Shell Sort Works
|
||||||
|
|
||||||
|
For our example and ease of understanding, we take the interval
|
||||||
|
of `4`. Make a virtual sub-list of all values located at the
|
||||||
|
interval of 4 positions. Here these values are
|
||||||
|
`{35, 14}`, `{33, 19}`, `{42, 27}` and `{10, 44}`
|
||||||
|
|
||||||
|
![Shellsort](https://www.tutorialspoint.com/data_structures_algorithms/images/shell_sort_gap_4.jpg)
|
||||||
|
|
||||||
|
We compare values in each sub-list and swap them (if necessary)
|
||||||
|
in the original array. After this step, the new array should
|
||||||
|
look like this
|
||||||
|
|
||||||
|
![Shellsort](https://www.tutorialspoint.com/data_structures_algorithms/images/shell_sort_step_1.jpg)
|
||||||
|
|
||||||
|
Then, we take interval of 2 and this gap generates two sub-lists
|
||||||
|
- `{14, 27, 35, 42}`, `{19, 10, 33, 44}`
|
||||||
|
|
||||||
|
![Shellsort](https://www.tutorialspoint.com/data_structures_algorithms/images/shell_sort_gap_2.jpg)
|
||||||
|
|
||||||
|
We compare and swap the values, if required, in the original array.
|
||||||
|
After this step, the array should look like this
|
||||||
|
|
||||||
|
![Shellsort](https://www.tutorialspoint.com/data_structures_algorithms/images/shell_sort_step_2.jpg)
|
||||||
|
|
||||||
|
Finally, we sort the rest of the array using interval of value 1.
|
||||||
|
Shell sort uses insertion sort to sort the array.
|
||||||
|
|
||||||
|
![Shellsort](https://www.tutorialspoint.com/data_structures_algorithms/images/shell_sort.jpg)
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
* [Tutorials Point](https://www.tutorialspoint.com/data_structures_algorithms/shell_sort_algorithm.htm)
|
||||||
|
* [Wikipedia](https://en.wikipedia.org/wiki/Shellsort)
|
41
src/algorithms/sorting/shell-sort/ShellSort.js
Normal file
41
src/algorithms/sorting/shell-sort/ShellSort.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import Sort from '../Sort';
|
||||||
|
|
||||||
|
export default class ShellSort extends Sort {
|
||||||
|
sort(originalArray) {
|
||||||
|
// Prevent original array from mutations.
|
||||||
|
const array = originalArray.slice(0);
|
||||||
|
|
||||||
|
// Define a gap distance.
|
||||||
|
let gap = Math.floor(array.length / 2);
|
||||||
|
|
||||||
|
// Until gap is bigger then zero do elements comparisons and swaps.
|
||||||
|
while (gap > 0) {
|
||||||
|
// Go and compare all distant element pairs.
|
||||||
|
for (let i = 0; i < (array.length - gap); i += 1) {
|
||||||
|
let currentIndex = i;
|
||||||
|
let gapShiftedIndex = i + gap;
|
||||||
|
|
||||||
|
while (currentIndex >= 0) {
|
||||||
|
// Call visiting callback.
|
||||||
|
this.callbacks.visitingCallback(array[currentIndex]);
|
||||||
|
|
||||||
|
// Compare and swap array elements if needed.
|
||||||
|
if (this.comparator.lessThen(array[gapShiftedIndex], array[currentIndex])) {
|
||||||
|
const tmp = array[currentIndex];
|
||||||
|
array[currentIndex] = array[gapShiftedIndex];
|
||||||
|
array[gapShiftedIndex] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
gapShiftedIndex = currentIndex;
|
||||||
|
currentIndex -= gap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shrink the gap.
|
||||||
|
gap = Math.floor(gap / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return sorted copy of an original array.
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
56
src/algorithms/sorting/shell-sort/__test__/ShellSort.test.js
Normal file
56
src/algorithms/sorting/shell-sort/__test__/ShellSort.test.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import ShellSort from '../ShellSort';
|
||||||
|
import {
|
||||||
|
equalArr,
|
||||||
|
notSortedArr,
|
||||||
|
reverseArr,
|
||||||
|
sortedArr,
|
||||||
|
SortTester,
|
||||||
|
} from '../../SortTester';
|
||||||
|
|
||||||
|
// Complexity constants.
|
||||||
|
const SORTED_ARRAY_VISITING_COUNT = 320;
|
||||||
|
const NOT_SORTED_ARRAY_VISITING_COUNT = 320;
|
||||||
|
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 320;
|
||||||
|
const EQUAL_ARRAY_VISITING_COUNT = 320;
|
||||||
|
|
||||||
|
describe('ShellSort', () => {
|
||||||
|
it('should sort array', () => {
|
||||||
|
SortTester.testSort(ShellSort);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should sort array with custom comparator', () => {
|
||||||
|
SortTester.testSortWithCustomComparator(ShellSort);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should visit EQUAL array element specified number of times', () => {
|
||||||
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
|
ShellSort,
|
||||||
|
equalArr,
|
||||||
|
EQUAL_ARRAY_VISITING_COUNT,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should visit SORTED array element specified number of times', () => {
|
||||||
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
|
ShellSort,
|
||||||
|
sortedArr,
|
||||||
|
SORTED_ARRAY_VISITING_COUNT,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should visit NOT SORTED array element specified number of times', () => {
|
||||||
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
|
ShellSort,
|
||||||
|
notSortedArr,
|
||||||
|
NOT_SORTED_ARRAY_VISITING_COUNT,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should visit REVERSE SORTED array element specified number of times', () => {
|
||||||
|
SortTester.testAlgorithmTimeComplexity(
|
||||||
|
ShellSort,
|
||||||
|
reverseArr,
|
||||||
|
REVERSE_SORTED_ARRAY_VISITING_COUNT,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user