This commit is contained in:
Chong Yao Jun 2024-07-17 10:42:09 +09:00 committed by GitHub
commit 7dcc57cd05
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 169 additions and 4 deletions

View File

@ -23,10 +23,7 @@ jobs:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- name: Install dependencies - name: Install dependencies
run: npm i run: npm ci
- name: Run linting
run: npm run lint
- name: Run tests - name: Run tests
run: npm run coverage run: npm run coverage

View File

@ -0,0 +1,58 @@
import Sort from '../Sort';
export default class CocktailShakerSort extends Sort {
sort(originalArray) {
// Flag that holds info about whether the swap has occur or not.
let swapped = true;
// Clone original array to prevent its modification.
const array = [...originalArray];
let start = 0;
let end = array.length;
while (swapped) {
// Reset the swapped flag on entering the loop,
// because it might be true from a previous iteration.
swapped = false;
// Loop forward same as the bubble sort
for (let i = start; i < end - 1; i += 1) {
// Call visiting callback.
this.callbacks.visitingCallback(array[i]);
if (this.comparator.greaterThan(array[i], array[i + 1])) {
[array[i], array[i + 1]] = [array[i + 1], array[i]];
swapped = true;
}
}
// Move the end point backward by one,
// because the item at the end point is already in its correct position.
end -= 1;
// If nothing swapped, then array is sorted.
if (swapped === false) {
break;
}
// Reset the swapped flag so that it can be used in the next stage
swapped = false;
// Loop backward, doing the same comparison as in the previous stage
for (let i = end - 1; i >= start; i -= 1) {
// Call visiting callback.
this.callbacks.visitingCallback(array[i]);
if (this.comparator.greaterThan(array[i], array[i + 1])) {
[array[i], array[i + 1]] = [array[i + 1], array[i]];
swapped = true;
}
}
// Move the start point forward by one,
// because the item at the start point is already in its correct position.
start += 1;
}
return array;
}
}

View File

@ -0,0 +1,23 @@
# Cocktail Shaker Sort
_Read this in other languages:_
[_简体中文_](README.zh-CN.md)
Cocktail Shaker Sort is an algorithm that is a Bidirectional Bubble Sort.
The algorithm extends bubble sort by operating in two directions.
While it improves on bubble sort by more quickly moving items to the beginning of the list, it provides only marginal performance improvements.
![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/e/ef/Sorting_shaker_sort_anim.gif)
## Complexity
| Name | Best | Average | Worst | Memory | Stable | Comments |
| ------------------------------ | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- |
| **Cocktail Shaker Sort** | n | n<sup>2</sup> | n<sup>2</sup> | 1 | Yes | |
## References
- [Cocktail Shaker Sort on Wikipedia](https://en.wikipedia.org/wiki/Cocktail_shaker_sort)
- [Bubble Sort on Wikipedia](https://en.wikipedia.org/wiki/Bubble_sort)

View File

@ -0,0 +1,23 @@
# 鸡尾酒排序
_Read this in other languages:_
[_English_](README.md)
鸡尾酒排序是一种双向气泡排序的算法。
该算法通过在两个方向上操作扩展了冒泡排序。虽然它通过更快速地将项目移到列表的开头而改进了冒泡排序,但它只提供了微弱的性能改进。
![Algorithm Visualization](https://upload.wikimedia.org/wikipedia/commons/e/ef/Sorting_shaker_sort_anim.gif)
## 复杂度
| 名称 | 最优 | 平均 | 最坏 | 内存 | 稳定 | 备注 |
| ------------------------------ | :-------------: | :-----------------: | :-----------------: | :-------: | :-------: | :-------- |
| **鸡尾酒排序** | n | n<sup>2</sup> | n<sup>2</sup> | 1 | 是 | |
## 参考
- [鸡尾酒排序(维基百科)](https://zh.wikipedia.org/wiki/%E9%B8%A1%E5%B0%BE%E9%85%92%E6%8E%92%E5%BA%8F)
- [冒泡排序(维基百科)](https://zh.wikipedia.org/wiki/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F)

View File

@ -0,0 +1,64 @@
import CocktailShakerSort from '../CocktailShakerSort';
import {
equalArr,
notSortedArr,
reverseArr,
sortedArr,
SortTester,
} from '../../SortTester';
// Complexity constants.
const SORTED_ARRAY_VISITING_COUNT = 19;
const NOT_SORTED_ARRAY_VISITING_COUNT = 159;
const REVERSE_SORTED_ARRAY_VISITING_COUNT = 200;
const EQUAL_ARRAY_VISITING_COUNT = 19;
describe('CocktailShakerSort', () => {
it('should sort array', () => {
SortTester.testSort(CocktailShakerSort);
});
it('should sort array with custom comparator', () => {
SortTester.testSortWithCustomComparator(CocktailShakerSort);
});
it('should do stable sorting', () => {
SortTester.testSortStability(CocktailShakerSort);
});
it('should sort negative numbers', () => {
SortTester.testNegativeNumbersSort(CocktailShakerSort);
});
it('should visit EQUAL array element specified number of times', () => {
SortTester.testAlgorithmTimeComplexity(
CocktailShakerSort,
equalArr,
EQUAL_ARRAY_VISITING_COUNT,
);
});
it('should visit SORTED array element specified number of times', () => {
SortTester.testAlgorithmTimeComplexity(
CocktailShakerSort,
sortedArr,
SORTED_ARRAY_VISITING_COUNT,
);
});
it('should visit NOT SORTED array element specified number of times', () => {
SortTester.testAlgorithmTimeComplexity(
CocktailShakerSort,
notSortedArr,
NOT_SORTED_ARRAY_VISITING_COUNT,
);
});
it('should visit REVERSE SORTED array element specified number of times', () => {
SortTester.testAlgorithmTimeComplexity(
CocktailShakerSort,
reverseArr,
REVERSE_SORTED_ARRAY_VISITING_COUNT,
);
});
});