Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the Fibonacci Search Algortihm #348

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/algorithms/search/fibonacci-search/README.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
@@ -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 changes: 51 additions & 0 deletions src/algorithms/search/fibonacci-search/fibonacciSearch.js
Original file line number Diff line number Diff line change
@@ -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;
}