Add the Fibonacci Search Algortihm

implemented fibonacci search with its test
This commit is contained in:
GharbiSlim 2019-04-25 13:13:17 +01:00 committed by GitHub
parent 94abfec91d
commit 9e45560379
3 changed files with 93 additions and 0 deletions

View 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 Fk1.
If the item matches, stop.
If the item is less than entry Fk1, discard the elements from positions Fk1 + 1 to n. Set k = k 1 and return to step 2.
If the item is greater than entry Fk1, discard the elements from positions 1 to Fk1. Renumber the remaining elements from 1 to Fk2, 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.

View File

@ -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);
});
});

View 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;
}