This commit is contained in:
GharbiSlim 2024-07-17 10:37:56 +09:00 committed by GitHub
commit c98b9eac4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 114 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,18 @@
import fibonacciSearch from '../fibonaccySearch';
describe('fibonacciSearch', () => {
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,69 @@
/** Author Slim Gharbi
* Fibonacci search implementation.
*
* @param {*[]} integers
* @param {*} elementToSearch
* @return {number}
*/
export default function fibonacciSearch(integers,elementToSearch) {
/* Initialize fibonacci numbers */
fibonacciMinus2 = 0; // (m-2)'th Fibonacci No.
fibonacciMinus1 = 1; // (m-1)'th Fibonacci No.
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
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;
}
/* If elementToSearch is greater than the value at index
fibonacciMinus2, cut the subarray after i+1 */
else if (integers[i] > elementToSearch) {
fibonacciNumber = fibonacciMinus2;
fibonacciMinus1 = fibonacciMinus1 - fibonacciMinus2;
fibonacciMinus2 = fibonacciNumber - fibonacciMinus1;
}
/* element found. return index */
else return i;
}
/* comparing the last element with elementToSearch */
if (fibonacciMinus1 == 1 && integers[offset+1] == elementToSearch)
return offset+1;
/*element not found. return -1 */
return -1;
}