mirror of
https://github.com/trekhleb/javascript-algorithms.git
synced 2025-07-08 02:14:56 +08:00
Add Interpolation Search.
This commit is contained in:
@ -86,6 +86,7 @@ a set of rules that precisely define a sequence of operations.
|
||||
* `B` [Linear Search](src/algorithms/search/linear-search)
|
||||
* `B` [Jump Search](src/algorithms/search/jump-search) (or Block Search) - search in sorted array
|
||||
* `B` [Binary Search](src/algorithms/search/binary-search) - search in sorted array
|
||||
* `B` [Interpolation Search](src/algorithms/search/interpolation-search) - search in uniformly distributed sorted array
|
||||
* **Sorting**
|
||||
* `B` [Bubble Sort](src/algorithms/sorting/bubble-sort)
|
||||
* `B` [Selection Sort](src/algorithms/sorting/selection-sort)
|
||||
|
40
src/algorithms/search/interpolation-search/README.md
Normal file
40
src/algorithms/search/interpolation-search/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# Interpolation Search
|
||||
|
||||
**Interpolation search** is an algorithm for searching for a key in an array that
|
||||
has been ordered by numerical values assigned to the keys (key values).
|
||||
|
||||
For example we have a sorted array of `n` uniformly distributed values `arr[]`,
|
||||
and we need to write a function to search for a particular element `x` in the array.
|
||||
|
||||
**Linear Search** finds the element in `O(n)` time, **Jump Search** takes `O(√ n)` time
|
||||
and **Binary Search** take `O(Log n)` time.
|
||||
|
||||
The **Interpolation Search** is an improvement over Binary Search for instances,
|
||||
where the values in a sorted array are _uniformly_ distributed. Binary Search
|
||||
always goes to the middle element to check. On the other hand, interpolation
|
||||
search may go to different locations according to the value of the key being
|
||||
searched. For example, if the value of the key is closer to the last element,
|
||||
interpolation search is likely to start search toward the end side.
|
||||
|
||||
To find the position to be searched, it uses following formula:
|
||||
|
||||
```
|
||||
// The idea of formula is to return higher value of pos
|
||||
// when element to be searched is closer to arr[hi]. And
|
||||
// smaller value when closer to arr[lo]
|
||||
pos = lo + ((x - arr[lo]) * (hi - lo) / (arr[hi] - arr[Lo]))
|
||||
|
||||
arr[] - Array where elements need to be searched
|
||||
x - Element to be searched
|
||||
lo - Starting index in arr[]
|
||||
hi - Ending index in arr[]
|
||||
```
|
||||
|
||||
## Complexity
|
||||
|
||||
**Time complexity**: `O(log(log(n))`
|
||||
|
||||
## References
|
||||
|
||||
- [GeeksForGeeks](https://www.geeksforgeeks.org/interpolation-search/)
|
||||
- [Wikipedia](https://en.wikipedia.org/wiki/Interpolation_search)
|
@ -0,0 +1,24 @@
|
||||
import interpolationSearch from '../interpolationSearch';
|
||||
|
||||
describe('interpolationSearch', () => {
|
||||
it('should search elements in sorted array of numbers', () => {
|
||||
expect(interpolationSearch([], 1)).toBe(-1);
|
||||
expect(interpolationSearch([1], 1)).toBe(0);
|
||||
expect(interpolationSearch([1], 0)).toBe(-1);
|
||||
expect(interpolationSearch([1, 1], 1)).toBe(0);
|
||||
expect(interpolationSearch([1, 2], 1)).toBe(0);
|
||||
expect(interpolationSearch([1, 2], 2)).toBe(1);
|
||||
expect(interpolationSearch([10, 20, 30, 40, 50], 40)).toBe(3);
|
||||
expect(interpolationSearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 14)).toBe(13);
|
||||
expect(interpolationSearch([1, 6, 7, 8, 12, 13, 14, 19, 21, 23, 24, 24, 24, 300], 24)).toBe(10);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 600)).toBe(-1);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 1)).toBe(0);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 2)).toBe(1);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 3)).toBe(2);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 700)).toBe(3);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 800)).toBe(4);
|
||||
expect(interpolationSearch([0, 2, 3, 700, 800, 1200, 1300, 1400, 1900], 1200)).toBe(5);
|
||||
expect(interpolationSearch([1, 2, 3, 700, 800, 1200, 1300, 1400, 19000], 800)).toBe(4);
|
||||
expect(interpolationSearch([0, 10, 11, 12, 13, 14, 15], 10)).toBe(1);
|
||||
});
|
||||
});
|
@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Interpolation search implementation.
|
||||
*
|
||||
* @param {*[]} sortedArray - sorted array with uniformly distributed values
|
||||
* @param {*} seekElement
|
||||
* @return {number}
|
||||
*/
|
||||
export default function interpolationSearch(sortedArray, seekElement) {
|
||||
let leftIndex = 0;
|
||||
let rightIndex = sortedArray.length - 1;
|
||||
|
||||
while (leftIndex <= rightIndex) {
|
||||
const rangeDelta = sortedArray[rightIndex] - sortedArray[leftIndex];
|
||||
const indexDelta = rightIndex - leftIndex;
|
||||
const valueDelta = seekElement - sortedArray[leftIndex];
|
||||
|
||||
// If valueDelta is less then zero it means that there is no seek element
|
||||
// exists in array since the lowest element from the range is already higher
|
||||
// then seek element.
|
||||
if (valueDelta < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// If range delta is zero then subarray contains all the same numbers
|
||||
// and thus there is nothing to search for unless this range is all
|
||||
// consists of seek number.
|
||||
if (!rangeDelta) {
|
||||
// By doing this we're also avoiding division by zero while
|
||||
// calculating the middleIndex later.
|
||||
return sortedArray[leftIndex] === seekElement ? leftIndex : -1;
|
||||
}
|
||||
|
||||
// Do interpolation of the middle index.
|
||||
const middleIndex = leftIndex + Math.floor(valueDelta * indexDelta / rangeDelta);
|
||||
|
||||
// If we've found the element just return its position.
|
||||
if (sortedArray[middleIndex] === seekElement) {
|
||||
return middleIndex;
|
||||
}
|
||||
|
||||
// Decide which half to choose for seeking next: left or right one.
|
||||
if (sortedArray[middleIndex] < seekElement) {
|
||||
// Go to the right half of the array.
|
||||
leftIndex = middleIndex + 1;
|
||||
} else {
|
||||
// Go to the left half of the array.
|
||||
rightIndex = middleIndex - 1;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
@ -23,5 +23,5 @@ minimum when `m = √n`. Therefore, the best step size is `m = √n`.
|
||||
|
||||
## References
|
||||
|
||||
- [Wikipedia](https://en.wikipedia.org/wiki/Jump_search)
|
||||
- [GeeksForGeeks](https://www.geeksforgeeks.org/jump-search/)
|
||||
- [Wikipedia](https://en.wikipedia.org/wiki/Jump_search)
|
||||
|
@ -3,7 +3,7 @@ import Comparator from '../../../utils/comparator/Comparator';
|
||||
/**
|
||||
* Jump (block) search implementation.
|
||||
*
|
||||
* @param {*[]} sortedArray.
|
||||
* @param {*[]} sortedArray
|
||||
* @param {*} seekElement
|
||||
* @param {function(a, b)} [comparatorCallback]
|
||||
* @return {number}
|
||||
|
Reference in New Issue
Block a user