mirror of
https://github.moeyy.xyz/https://github.com/trekhleb/javascript-algorithms.git
synced 2024-09-20 07:43:04 +08:00
Merge 9e45560379
into ca3d16dcce
This commit is contained in:
commit
25dbc17bbd
27
src/algorithms/search/fibonacci-search/README.md
Normal file
27
src/algorithms/search/fibonacci-search/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
# Fibonacci Search Algorithm
|
||||
Let k be defined as an element in F, the array of Fibonacci numbers. n = Fm is the array size. If n is not a Fibonacci number, let Fm be the smallest number in F that is greater than n.
|
||||
|
||||
The array of Fibonacci numbers is defined where Fk+2 = Fk+1 + Fk, when k ≥ 0, F1 = 1, and F0 = 0.
|
||||
|
||||
To test whether an item is in the list of ordered numbers, follow these steps:
|
||||
```sh
|
||||
Set k = m.
|
||||
If k = 0, stop. There is no match; the item is not in the array.
|
||||
Compare the item against element in Fk−1.
|
||||
If the item matches, stop.
|
||||
If the item is less than entry Fk−1, discard the elements from positions Fk−1 + 1 to n. Set k = k − 1 and return to step 2.
|
||||
If the item is greater than entry Fk−1, discard the elements from positions 1 to Fk−1. Renumber the remaining elements from 1 to Fk−2, set k = k − 2, and return to step 2.
|
||||
Alternative implementation (from "Sorting and Searching" by Knuth[4]):
|
||||
|
||||
Given a table of records R1, R2, ..., RN whose keys are in increasing order K1 < K2 < ... < KN, the algorithm searches for a given argument K. Assume N+1 = Fk+1
|
||||
|
||||
Step 1. [Initialize] i ← Fk, p ← Fk-1, q ← Fk-2 (throughout the algorithm, p and q will be consecutive Fibonacci numbers)
|
||||
|
||||
Step 2. [Compare] If K < Ki, go to Step 3; if K > Ki go to Step 4; and if K = Ki, the algorithm terminates successfully.
|
||||
|
||||
Step 3. [Decrease i] If q=0, the algorithm terminates unsuccessfully. Otherwise set (i, p, q) ← (p, q, p - q) (which moves p and q one position back in the Fibonacci sequence); then return to Step 2
|
||||
|
||||
Step 4. [Increase i] If p=1, the algorithm terminates unsuccessfully. Otherwise set (i,p,q) ← (i + q, p - q, 2q - p) (which moves p and q two positions back in the Fibonacci sequence); and return to Step 2
|
||||
```
|
||||
The two variants of the algorithm presented above always divide the current interval into a larger and a smaller subinterval. The original algorithm,[1] however, would divide the new interval into a smaller and a larger subinterval in Step 4. This has the advantage that the new i is closer to the old i and is more suitable for accelerating searching on magnetic tape.
|
||||
|
@ -0,0 +1,15 @@
|
||||
import fibonacciSearch from '../fibonacciSearch';
|
||||
|
||||
describe('fibonacciSearch', () => {
|
||||
it('should search number in sorted array', () => {
|
||||
expect(fibonacciSearch([], 1)).toBe(-1);
|
||||
expect(fibonacciSearch([1], 1)).toBe(0);
|
||||
expect(fibonacciSearch([1, 2], 1)).toBe(0);
|
||||
expect(fibonacciSearch([1, 2], 2)).toBe(1);
|
||||
expect(fibonacciSearch([1, 5, 10, 12], 1)).toBe(0);
|
||||
expect(fibonacciSearch([1, 5, 10, 12, 14, 17, 22, 100], 17)).toBe(5);
|
||||
expect(fibonacciSearch([1, 5, 10, 12, 14, 17, 22, 100], 1)).toBe(0);
|
||||
expect(fibonacciSearch([1, 5, 10, 12, 14, 17, 22, 100], 100)).toBe(7);
|
||||
expect(fibonacciSearch([1, 5, 10, 12, 14, 17, 22, 100], 0)).toBe(-1);
|
||||
});
|
||||
});
|
51
src/algorithms/search/fibonacci-search/fibonacciSearch.js
Normal file
51
src/algorithms/search/fibonacci-search/fibonacciSearch.js
Normal file
@ -0,0 +1,51 @@
|
||||
/** Author Slim Gharbi
|
||||
* Fibonacci search implementation.
|
||||
*
|
||||
* @param {*[]} integers
|
||||
* @param {*} elementToSearch
|
||||
* @return {number}
|
||||
*/
|
||||
export default function fibonacciSearch(integers, elementToSearch) {
|
||||
let i;
|
||||
|
||||
/* Initialize fibonacci numbers */
|
||||
let fibonacciMinus2 = 0;// (m-2)'th Fibonacci No.
|
||||
let fibonacciMinus1 = 1;// (m-1)'th Fibonacci No.
|
||||
let fibonacciNumber = fibonacciMinus2 + fibonacciMinus1; // m'th Fibonacci
|
||||
/* fibonacciNumber is going to store the smallest
|
||||
Fibonacci Number greater than or equal to the length of the array */
|
||||
while (fibonacciNumber < integers.length) {
|
||||
fibonacciMinus2 = fibonacciMinus1;
|
||||
fibonacciMinus1 = fibonacciNumber;
|
||||
fibonacciNumber = fibonacciMinus2 + fibonacciMinus1;
|
||||
}
|
||||
// Marks the eliminated range from front
|
||||
let offset = -1;
|
||||
/* while there are elements to be inspected.
|
||||
Note that we compare integers[fibonacciMinus2] with elementToSearch.
|
||||
When fibonacciNumber becomes 1, fibonacciMinus2 becomes 0 */
|
||||
while (fibonacciNumber > 1) {
|
||||
// Check if fibonacciMinus2 is a valid location
|
||||
i = Math.min((offset + fibonacciMinus2), (integers.length - 1));
|
||||
/* If elementToSearch is greater than the value at
|
||||
index fibonacciMinus2, cut the subarray array
|
||||
from offset to i */
|
||||
if (integers[i] < elementToSearch) {
|
||||
fibonacciNumber = fibonacciMinus1;
|
||||
fibonacciMinus1 = fibonacciMinus2;
|
||||
fibonacciMinus2 = fibonacciNumber - fibonacciMinus1;
|
||||
offset = i;
|
||||
} else if (integers[i] > elementToSearch) {
|
||||
fibonacciNumber = fibonacciMinus2;
|
||||
fibonacciMinus1 -= fibonacciMinus2;
|
||||
fibonacciMinus2 = fibonacciNumber - fibonacciMinus1;
|
||||
/* If elementToSearch is greater than the value at index
|
||||
fibonacciMinus2, cut the subarray after i+1 */
|
||||
} else return i;
|
||||
// element found. return index
|
||||
}
|
||||
// comparing the last element with elementToSearch
|
||||
if (fibonacciMinus1 === 1 && integers[offset + 1] === elementToSearch) return offset + 1;
|
||||
// element not found. return -1
|
||||
return -1;
|
||||
}
|
Loading…
Reference in New Issue
Block a user