diff --git a/src/algorithms/sorting/README.md b/src/algorithms/sorting/README.md new file mode 100644 index 0000000..011cfe1 --- /dev/null +++ b/src/algorithms/sorting/README.md @@ -0,0 +1,19 @@ +# Sorting algorithms + +The assumptions is that the algorithms will be sorting numeric arrays. + +## Classification + +Sorting algorithms can be classified by: + +- Computational complexity + Best, worst and average case behavior in terms of the size of the list. For typical serial sorting algorithms, good behavior is O(n log n), with parallel sort in O(log2 n), and bad behavior is O(n2). Ideal behavior for a serial sort is O(n), but this is not possible in the average case. Optimal parallel sorting is O(log n). + Swaps for "in-place" algorithms. +- Memory complexity. In particular, some sorting algorithms are "in-place". Strictly, an in-place sort needs only O(1) memory beyond the items being sorted; sometimes O(log n) additional memory is considered "in-place". +- Recursion: Some algorithms are either recursive or non-recursive, while others may be both (e.g., merge sort). +- Stability: stable sorting algorithms maintain the relative order of records with equal keys (i.e., values). +- Whether or not they are a comparison sort. A comparison sort examines the data only by comparing two elements with a comparison operator. +- General method: insertion, exchange, selection, merging, etc. Exchange sorts include bubble sort and quicksort. Selection sorts include cycle sort and heapsort. +- Whether the algorithm is serial or parallel. The remainder of this discussion almost exclusively concentrates upon serial algorithms and assumes serial operation. +- Adaptability: Whether or not the presortedness of the input affects the running time. Algorithms that take this into account are known to be adaptive. +- Online: An algorithm such as Insertion Sort that is online can sort a constant stream of input. diff --git a/src/algorithms/sorting/bubble-sort.test.ts b/src/algorithms/sorting/bubble-sort.test.ts new file mode 100644 index 0000000..1a07b77 --- /dev/null +++ b/src/algorithms/sorting/bubble-sort.test.ts @@ -0,0 +1,75 @@ +import SortingOrder from 'src/util/SortingOrder'; +import { bubbleSort, sort } from './bubble-sort'; + +const params = [ + { + label: 'Reverse ordering for Ascending', + input: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], + sortingOrder: SortingOrder.Ascending, + expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + }, + { + label: 'Reverse ordering for Descending', + input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + sortingOrder: SortingOrder.Descending, + expected: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], + }, + { + label: 'Same Ascending order', + input: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + sortingOrder: SortingOrder.Ascending, + expected: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + }, + { + label: 'Same Descending order', + input: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], + sortingOrder: SortingOrder.Descending, + expected: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], + }, + { + label: 'Randomly sorted with duplicates for Ascending', + input: [15, 2, 4, 1, 7, 22, 5, -3, 9, -4, 5, 49, 993, 1, 10, 1, 111, 9, 2], + sortingOrder: SortingOrder.Ascending, + expected: [], + }, + { + label: 'Randomly sorted with duplicates for Descending', + input: [15, 2, 4, 1, 7, 22, 5, -3, 9, -4, 5, 49, 993, 1, 10, 1, 111, 9, 2], + sortingOrder: SortingOrder.Descending, + expected: [], + }, + { + label: 'Only one element for Ascending', + input: [7], + sortingOrder: SortingOrder.Ascending, + expected: [7], + }, + { + label: 'Only one element for Descending', + input: [7], + sortingOrder: SortingOrder.Descending, + expected: [7], + }, + { + label: 'Empty array for Ascending', + input: [], + sortingOrder: SortingOrder.Ascending, + expected: [], + }, + { + label: 'Empty array for Descending', + input: [], + sortingOrder: SortingOrder.Descending, + expected: [], + }, +]; + +test.each(params)('bubbleSort - $label', ({ input, sortingOrder, expected }) => { + bubbleSort(input, sortingOrder); + expect(input).toEqual(expected); +}); + +test.each(params)('sort - $label', ({ input, sortingOrder, expected }) => { + sort(input, sortingOrder); + expect(input).toEqual(expected); +}); diff --git a/src/algorithms/sorting/bubble-sort.ts b/src/algorithms/sorting/bubble-sort.ts new file mode 100644 index 0000000..0ce684f --- /dev/null +++ b/src/algorithms/sorting/bubble-sort.ts @@ -0,0 +1,59 @@ +import SortingOrder from 'src/util/SortingOrder'; + +export function bubbleSort(input: number[], sortingOrder: SortingOrder) { + if (input.length <= 1) return; + + for (let i = 0; i < input.length - 1; i++) { + for (let j = i + 1; j < input.length; j++) { + if ( + (sortingOrder === SortingOrder.Ascending && input[i] > input[j]) || + (sortingOrder === SortingOrder.Descending && input[i] < input[j]) + ) { + const temp = input[j]; + input[j] = input[i]; + input[i] = temp; + } + } + } +} + +// 5 3 10 11 7 9 +// 3 5 10 11 7 9 +// 3 5 10 11 7 9 +// 3 5 10 11 7 9 +// 3 5 10 7 11 9 +// 3 5 10 7 9 11 +// 3 5 10 7 9 11 +// 3 5 10 7 9 11 +// 3 5 7 10 9 11 +// 3 5 7 9 10 11 + +export function sort(input: number[], sortingOrder: SortingOrder) { + if (input.length <= 1) return; + + let swap = true; + let j = 1; + + while (swap) { + let atLeastOneSwap = false; + + for (let i = 0; i < input.length - j; i++) { + if ( + (sortingOrder === SortingOrder.Ascending && input[i] > input[i + 1]) || + (sortingOrder === SortingOrder.Descending && input[i] < input[i + 1]) + ) { + const temp = input[i + 1]; + input[i + 1] = input[i]; + input[i] = temp; + atLeastOneSwap = true; + } + console.log(input); + } + + if (!atLeastOneSwap) { + swap = false; + } else { + j++; + } + } +}