From e3d90576a92e372dbcbb6109571774818bfb0b4c Mon Sep 17 00:00:00 2001 From: GohJunLe <108907711+GohJunLe@users.noreply.github.com> Date: Tue, 9 Aug 2022 08:36:48 +0800 Subject: [PATCH] Add exponential search --- .../__test__/exponentialSearch.test.js | 35 ++++++++++ .../exponential-search/exponentialSearch.js | 67 +++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js create mode 100644 src/algorithms/search/exponential-search/exponentialSearch.js diff --git a/src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js b/src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js new file mode 100644 index 00000000..0816af2b --- /dev/null +++ b/src/algorithms/search/exponential-search/__test__/exponentialSearch.test.js @@ -0,0 +1,35 @@ +import exponentialSearch from '../exponentialSearch'; + +describe('exponentialSearch', () => { + it('should search number in sorted array', () => { + expect(exponentialSearch([], 1)).toBe(-1); + expect(exponentialSearch([1], 1)).toBe(0); + expect(exponentialSearch([1, 2], 1)).toBe(0); + expect(exponentialSearch([1, 2], 2)).toBe(1); + expect(exponentialSearch([1, 5, 10, 12], 1)).toBe(0); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 17)).toBe(5); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 1)).toBe(0); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 100)).toBe(7); + expect(exponentialSearch([1, 5, 10, 12, 14, 17, 22, 100], 0)).toBe(-1); + }); + + it('should search object in sorted array', () => { + const sortedArrayOfObjects = [ + { key: 1, value: 'value1' }, + { key: 2, value: 'value2' }, + { key: 3, value: 'value3' }, + { key: 4, value: 'value4' }, + ]; + + const comparator = (a, b) => { + if (a.key === b.key) return 0; + return a.key < b.key ? -1 : 1; + }; + + expect(exponentialSearch([], { key: 1 }, comparator)).toBe(-1); + expect(exponentialSearch(sortedArrayOfObjects, { key: 4 }, comparator)).toBe(3); + expect(exponentialSearch(sortedArrayOfObjects, { key: 1 }, comparator)).toBe(0); + expect(exponentialSearch(sortedArrayOfObjects, { key: 2 }, comparator)).toBe(1); + expect(exponentialSearch(sortedArrayOfObjects, { key: 3 }, comparator)).toBe(2); + }); +}); diff --git a/src/algorithms/search/exponential-search/exponentialSearch.js b/src/algorithms/search/exponential-search/exponentialSearch.js new file mode 100644 index 00000000..b9c69693 --- /dev/null +++ b/src/algorithms/search/exponential-search/exponentialSearch.js @@ -0,0 +1,67 @@ +import Comparator from '../../../utils/comparator/Comparator'; + +/** + * Binary search implementation. + * + * @param {*[]} sortedArray + * @param {*} startIndex + * @param {*} endIndex + * @param {*} seekElement + * @param {function(a, b)} [comparatorCallback] + * @return {number} + */ + +function binarySearch(sortedArray, startIndex, endIndex, seekElement, comparatorCallback) +{ + const comparator = new Comparator(comparatorCallback); + + if (endIndex >= startIndex) + { + const middleIndex = startIndex + Math.floor((endIndex - startIndex) / 2); + + // If the element is present at the middle itself + if (comparator.equal(sortedArray[middleIndex], seekElement)) + return middleIndex; + + // If element is smaller than middleIndex, then it can only be present n left subarray + if (comparator.greaterThan(sortedArray[middleIndex], seekElement)){ + return binarySearch(sortedArray, startIndex, middleIndex - 1, seekElement, comparatorCallback); + }else{ + // Else the element can only be present in right subarray + return binarySearch(sortedArray, middleIndex + 1, endIndex, seekElement, comparatorCallback); + } + + } + + // We reach here when element is not present in array + return -1; +} + +/** + * Exponential search implementation. + * + * @param {*[]} sortedArray + * @param {*} seekElement + * @param {function(a, b)} [comparatorCallback] + * @return {number} + */ + +export default function exponentialSearch(sortedArray, seekElement, comparatorCallback) +{ + const comparator = new Comparator(comparatorCallback); + const length = sortedArray.length; + + // If element is present at first location itself + if(sortedArray.length != 0){ + if (comparator.equal(sortedArray[0], seekElement)) + return 0; + } + + // Find range for binary search by repeated doubling + let range = 1; + while (range < length && comparator.lessThanOrEqual(sortedArray[range], seekElement)) + range = range * 2; + + // Call binary search for the found range. + return binarySearch(sortedArray, range/2, Math.min(range, length - 1), seekElement, comparatorCallback); +} \ No newline at end of file