From 29e96bcacecc015002963130455055c8c79e941c Mon Sep 17 00:00:00 2001 From: wfatec Date: Fri, 25 Jan 2019 11:24:56 +0800 Subject: [PATCH 1/2] add new mergesort method without recursion --- .../merge-sort/MergeSortWithoutRecursion.js | 66 +++++++++++++++++++ .../MergeSortWithoutRecursion.test.js | 66 +++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js create mode 100644 src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js diff --git a/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js b/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js new file mode 100644 index 00000000..65fce231 --- /dev/null +++ b/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js @@ -0,0 +1,66 @@ +import Sort from '../Sort'; + +export default class MergeSortWithoutRecursion extends Sort { + sort(originalArray) { + // Call visiting callback. + this.callbacks.visitingCallback(null); + + // If array is empty or consists of one element then return this array since it is sorted. + if (originalArray.length <= 1) { + return originalArray; + } + + let step = 1; + let left; + let right; + + while (step < originalArray.length) { + left = 0; + right = step; + + while (right + step < originalArray.length) { + this.mergeArrays(originalArray, left, left + step, right, right + step); + left = right + step; + right = left + step; + } + + if (right < originalArray.length) { + this.mergeArrays(originalArray, left, left + step, right, originalArray.length); + } + step *= 2; + } + + return originalArray; + } + + mergeArrays(originalArray, startLeft, stopLeft, startRight, stopRight) { + const arr = originalArray; + const rightArr = new Array(stopRight - startRight + 1); + const leftArr = new Array(stopLeft - startRight + 1); + let k = startRight; + + for (let i = 0; i < (rightArr.length - 1); i += 1) { + rightArr[i] = arr[k]; + k += 1; + } + k = startLeft; + for (let i = 0; i < (leftArr.length - 1); i += 1) { + leftArr[i] = arr[k]; + k += 1; + } + + rightArr[rightArr.length - 1] = Infinity; // 哨兵值 + leftArr[leftArr.length - 1] = Infinity; // 哨兵值 + let m = 0; + let n = 0; + for (let i = startLeft; i < stopRight; i += 1) { + if (leftArr[m] <= rightArr[n]) { + arr[i] = leftArr[m]; + m += 1; + } else { + arr[i] = rightArr[n]; + n += 1; + } + } + } +} diff --git a/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js b/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js new file mode 100644 index 00000000..bf1eae5b --- /dev/null +++ b/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js @@ -0,0 +1,66 @@ +import MergeSortWithoutRecursion from '../MergeSort'; +import { + equalArr, + notSortedArr, + reverseArr, + sortedArr, + SortTester, +} from '../../SortTester'; + +// Complexity constants. +const SORTED_ARRAY_VISITING_COUNT = 79; +const NOT_SORTED_ARRAY_VISITING_COUNT = 102; +const REVERSE_SORTED_ARRAY_VISITING_COUNT = 87; +const EQUAL_ARRAY_VISITING_COUNT = 79; + +const MergeSort = MergeSortWithoutRecursion; + +describe('MergeSort', () => { + it('should sort array', () => { + SortTester.testSort(MergeSort); + }); + + it('should sort array with custom comparator', () => { + SortTester.testSortWithCustomComparator(MergeSort); + }); + + it('should do stable sorting', () => { + SortTester.testSortStability(MergeSort); + }); + + it('should sort negative numbers', () => { + SortTester.testNegativeNumbersSort(MergeSort); + }); + + it('should visit EQUAL array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + equalArr, + EQUAL_ARRAY_VISITING_COUNT, + ); + }); + + it('should visit SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + sortedArr, + SORTED_ARRAY_VISITING_COUNT, + ); + }); + + it('should visit NOT SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + notSortedArr, + NOT_SORTED_ARRAY_VISITING_COUNT, + ); + }); + + it('should visit REVERSE SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + reverseArr, + REVERSE_SORTED_ARRAY_VISITING_COUNT, + ); + }); +}); From 65b12061cf9993d358722a054fc34967e945d5c7 Mon Sep 17 00:00:00 2001 From: wfatec Date: Fri, 25 Jan 2019 12:10:01 +0800 Subject: [PATCH 2/2] [fix] replace CRLF with LF --- .../merge-sort/MergeSortWithoutRecursion.js | 132 +++++++++--------- .../MergeSortWithoutRecursion.test.js | 132 +++++++++--------- 2 files changed, 132 insertions(+), 132 deletions(-) diff --git a/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js b/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js index 65fce231..86a4d05e 100644 --- a/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js +++ b/src/algorithms/sorting/merge-sort/MergeSortWithoutRecursion.js @@ -1,66 +1,66 @@ -import Sort from '../Sort'; - -export default class MergeSortWithoutRecursion extends Sort { - sort(originalArray) { - // Call visiting callback. - this.callbacks.visitingCallback(null); - - // If array is empty or consists of one element then return this array since it is sorted. - if (originalArray.length <= 1) { - return originalArray; - } - - let step = 1; - let left; - let right; - - while (step < originalArray.length) { - left = 0; - right = step; - - while (right + step < originalArray.length) { - this.mergeArrays(originalArray, left, left + step, right, right + step); - left = right + step; - right = left + step; - } - - if (right < originalArray.length) { - this.mergeArrays(originalArray, left, left + step, right, originalArray.length); - } - step *= 2; - } - - return originalArray; - } - - mergeArrays(originalArray, startLeft, stopLeft, startRight, stopRight) { - const arr = originalArray; - const rightArr = new Array(stopRight - startRight + 1); - const leftArr = new Array(stopLeft - startRight + 1); - let k = startRight; - - for (let i = 0; i < (rightArr.length - 1); i += 1) { - rightArr[i] = arr[k]; - k += 1; - } - k = startLeft; - for (let i = 0; i < (leftArr.length - 1); i += 1) { - leftArr[i] = arr[k]; - k += 1; - } - - rightArr[rightArr.length - 1] = Infinity; // 哨兵值 - leftArr[leftArr.length - 1] = Infinity; // 哨兵值 - let m = 0; - let n = 0; - for (let i = startLeft; i < stopRight; i += 1) { - if (leftArr[m] <= rightArr[n]) { - arr[i] = leftArr[m]; - m += 1; - } else { - arr[i] = rightArr[n]; - n += 1; - } - } - } -} +import Sort from '../Sort'; + +export default class MergeSortWithoutRecursion extends Sort { + sort(originalArray) { + // Call visiting callback. + this.callbacks.visitingCallback(null); + + // If array is empty or consists of one element then return this array since it is sorted. + if (originalArray.length <= 1) { + return originalArray; + } + + let step = 1; + let left; + let right; + + while (step < originalArray.length) { + left = 0; + right = step; + + while (right + step < originalArray.length) { + this.mergeArrays(originalArray, left, left + step, right, right + step); + left = right + step; + right = left + step; + } + + if (right < originalArray.length) { + this.mergeArrays(originalArray, left, left + step, right, originalArray.length); + } + step *= 2; + } + + return originalArray; + } + + mergeArrays(originalArray, startLeft, stopLeft, startRight, stopRight) { + const arr = originalArray; + const rightArr = new Array(stopRight - startRight + 1); + const leftArr = new Array(stopLeft - startRight + 1); + let k = startRight; + + for (let i = 0; i < (rightArr.length - 1); i += 1) { + rightArr[i] = arr[k]; + k += 1; + } + k = startLeft; + for (let i = 0; i < (leftArr.length - 1); i += 1) { + leftArr[i] = arr[k]; + k += 1; + } + + rightArr[rightArr.length - 1] = Infinity; // 哨兵值 + leftArr[leftArr.length - 1] = Infinity; // 哨兵值 + let m = 0; + let n = 0; + for (let i = startLeft; i < stopRight; i += 1) { + if (leftArr[m] <= rightArr[n]) { + arr[i] = leftArr[m]; + m += 1; + } else { + arr[i] = rightArr[n]; + n += 1; + } + } + } +} diff --git a/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js b/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js index bf1eae5b..9c9f6d99 100644 --- a/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js +++ b/src/algorithms/sorting/merge-sort/__test__/MergeSortWithoutRecursion.test.js @@ -1,66 +1,66 @@ -import MergeSortWithoutRecursion from '../MergeSort'; -import { - equalArr, - notSortedArr, - reverseArr, - sortedArr, - SortTester, -} from '../../SortTester'; - -// Complexity constants. -const SORTED_ARRAY_VISITING_COUNT = 79; -const NOT_SORTED_ARRAY_VISITING_COUNT = 102; -const REVERSE_SORTED_ARRAY_VISITING_COUNT = 87; -const EQUAL_ARRAY_VISITING_COUNT = 79; - -const MergeSort = MergeSortWithoutRecursion; - -describe('MergeSort', () => { - it('should sort array', () => { - SortTester.testSort(MergeSort); - }); - - it('should sort array with custom comparator', () => { - SortTester.testSortWithCustomComparator(MergeSort); - }); - - it('should do stable sorting', () => { - SortTester.testSortStability(MergeSort); - }); - - it('should sort negative numbers', () => { - SortTester.testNegativeNumbersSort(MergeSort); - }); - - it('should visit EQUAL array element specified number of times', () => { - SortTester.testAlgorithmTimeComplexity( - MergeSort, - equalArr, - EQUAL_ARRAY_VISITING_COUNT, - ); - }); - - it('should visit SORTED array element specified number of times', () => { - SortTester.testAlgorithmTimeComplexity( - MergeSort, - sortedArr, - SORTED_ARRAY_VISITING_COUNT, - ); - }); - - it('should visit NOT SORTED array element specified number of times', () => { - SortTester.testAlgorithmTimeComplexity( - MergeSort, - notSortedArr, - NOT_SORTED_ARRAY_VISITING_COUNT, - ); - }); - - it('should visit REVERSE SORTED array element specified number of times', () => { - SortTester.testAlgorithmTimeComplexity( - MergeSort, - reverseArr, - REVERSE_SORTED_ARRAY_VISITING_COUNT, - ); - }); -}); +import MergeSortWithoutRecursion from '../MergeSort'; +import { + equalArr, + notSortedArr, + reverseArr, + sortedArr, + SortTester, +} from '../../SortTester'; + +// Complexity constants. +const SORTED_ARRAY_VISITING_COUNT = 79; +const NOT_SORTED_ARRAY_VISITING_COUNT = 102; +const REVERSE_SORTED_ARRAY_VISITING_COUNT = 87; +const EQUAL_ARRAY_VISITING_COUNT = 79; + +const MergeSort = MergeSortWithoutRecursion; + +describe('MergeSort', () => { + it('should sort array', () => { + SortTester.testSort(MergeSort); + }); + + it('should sort array with custom comparator', () => { + SortTester.testSortWithCustomComparator(MergeSort); + }); + + it('should do stable sorting', () => { + SortTester.testSortStability(MergeSort); + }); + + it('should sort negative numbers', () => { + SortTester.testNegativeNumbersSort(MergeSort); + }); + + it('should visit EQUAL array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + equalArr, + EQUAL_ARRAY_VISITING_COUNT, + ); + }); + + it('should visit SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + sortedArr, + SORTED_ARRAY_VISITING_COUNT, + ); + }); + + it('should visit NOT SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + notSortedArr, + NOT_SORTED_ARRAY_VISITING_COUNT, + ); + }); + + it('should visit REVERSE SORTED array element specified number of times', () => { + SortTester.testAlgorithmTimeComplexity( + MergeSort, + reverseArr, + REVERSE_SORTED_ARRAY_VISITING_COUNT, + ); + }); +});