using System;
using System.Collections.Generic;
namespace TestCSharp
{
class Program
{
// 斐波那契数列:从第三个元素开始,本项是前两项的和。即F[k] = F[k-1] + F[k-2]
// 斐波那契数列的性质:长度为 F[k-1] - 1 的数列,去掉对应切分点元素,可以分成左右两个子数列。
// 左边数列长度为 F[k-1] - 1, 右边数列长度为 F[k-2] - 1, 切分点元素占位长度为1, 因此总长度为 F[k-1] - 1 == F[k-1] - 1 + 1 + F[k-2] - 1
static void Main(string[] args)
{
int[] array = { 1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68 };
Console.WriteLine("result: " + FibonacciSearch(array, 68));
Console.ReadKey();
}
public static int FibonacciSearch(int[] list, int targetValue)
{
// create fibonacci array.
int[] F = CreateFibonacciArray(list.Length); // TODO
int k = 0;
while (list.Length > F[k] - 1)
{
k++;
}
// create a array whose length is F[k] - 1.
int[] fullList = new int[F[k] - 1];
for (int i = 0, length = fullList.Length; i < length; i++)
{
if (i < list.Length)
{
fullList[i] = list[i];
}
else
{
fullList[i] = list[list.Length - 1];
}
}
// recurse mode.
return RecurseFind(fullList, F, targetValue, 0, list.Length - 1, k);
// find target value.
int low = 0;
int high = list.Length - 1;
int mid = 0;
while (low <= high)
{
mid = low + F[k - 1] - 1;
if (targetValue < fullList[mid])
{
high = mid - 1;
k = k - 1;
}
else if (targetValue > fullList[mid])
{
low = mid + 1;
k = k - 2;
}
else
{
if (mid < list.Length)
{
return mid;
}
return list.Length - 1;
}
}
return -1;
}
public static int[] CreateFibonacciArray(int length)
{
if (length < 2)
{
return null;
}
int[] array = new int[length];
array[0] = 1;
array[1] = 1;
for (int i = 2, max = array.Length; i < max; i++)
{
array[i] = array[i - 1] + array[i - 2];
}
return array;
}
static int RecurseFind(int[] fullList, int[] F, int targetValue, int low, int high, int k)
{
if (fullList == null || fullList.Length == 0 || targetValue < fullList[low]
|| targetValue > fullList[high] || low > high)
{
return -1;
}
int mid = low + F[k - 1] - 1;
if (targetValue < fullList[mid])
{
return RecurseFind(fullList, F, targetValue, low, mid - 1, k - 1);
}
else if (targetValue > fullList[mid])
{
return RecurseFind(fullList, F, targetValue, mid + 1, high, k - 2);
}
else
{
if (mid <= high)
{
return mid;
}
return high;
}
}
}
}