斐波那契查找

目录

斐波那契查找的基本介绍

斐波那契(黄金分割法)原理

斐波那契查找的代码实现


斐波那契查找的基本介绍

在中学阶段我们都学过黄金分割比为0.618,在斐波那契数列中,相邻两个数的比例,无限接近0.618

斐波那契(黄金分割法)原理

斐波那契查找与前两种查找方法相似,仅仅是改变了中间节点mid的位置,mid不再是由二分或者差值得到,而是位于黄金分割点附近。即:mid=left+F[k-1]-1,(F表示斐波那契数列),如下图所示:

斐波那契查找_第1张图片

对于F[k]-1的理解

(1)因为斐波那契数列满足:F[k]=F[k-1]+F[k-2],所以F[k]-1=(F[k-1]-1)+(F[k-2]-1)+1

该式说明:对于长度为F[k]-1的斐波那契数列,我们总能找到一个mid,将其分为长度为F[k-1]-1和F[k-2]-1两个部分。

(2)类似的,对于每一子段,也可以用相同的方法分割。

(3)但是顺序表的长度不一定为F[k]-1,所以我们要对原先的表进行扩容。这里只需要让F[k]-1>=n就可以。新增的位置都赋值为n位置的值

    int k = 0;//记录F的下标
	//找到满足条件的下标 F[k]-1>n
	while (n > F[k] - 1) {
		++k;
	}

	int* tmp = new int[F[k] - 1]; //将数组扩展到F[k]-1的长度
	memcpy(tmp, a, n * sizeof(int));
	//扩展数组,多出的部分按照最后一个元素处理
	for (int i = n; i < F[k] - 1; i++) {
		tmp[i] = a[n - 1];
	}

斐波那契查找的代码实现

(1)首先我们要得到一个斐波那契数列

#define max_size 20

void Fibonacci(int* F)
{
	F[0] = 1;
	F[1] = 1;
	for (int i = 2; i < max_size - 1; i++) {
		F[i] = F[i - 1] + F[i - 2];
	}
}

(2)先扩容,然后进行查找

int Fibonacci_Search(int* a, int n, int k) {
	int low = 0;
	int high = n - 1;

	int F[max_size];
	Fibonacci(F);

	int k = 0;//记录F的下标
	//找到满足条件的下标 F[k]-1>n
	while (n > F[k] - 1) {
		++k;
	}

	int* tmp = new int[F[k] - 1]; //将数组扩展到F[k]-1的长度
	memcpy(tmp, a, n * sizeof(int));
	//扩展数组,多出的部分按照最后一个元素处理
	for (int i = n; i < F[k] - 1; i++) {
		tmp[i] = a[n - 1];
	}

	while (left <= right) {
		int mid = low + F[k - 1] - 1;
		if (k < tmp[mid]) {
			high = mid - 1;
			k-=1;
		}
		else if (k > tmp[mid]) {
			low = mid + 1;
			k -= 2;
		}
		else
		{
			if (mid < n) {
				return mid;//说明mid即为查找到的位置
			}
			else{
				return n - 1;//mid>=n说明是在扩展的地方找到的,返回n-1(最后一位)
			}
		}
	}
	return -1;
}

这里需要理解的点

斐波那契查找_第2张图片

(1)对k的不同处理:

如果当k

如果当k>a[mid]时,说明新范围是mid+1到第high个,此时范围个数为F[k-2]-1(即原先的右区间)

所以要对k进行k-=1(下一次在左区间细分)或者k-=2(下一次在右区间细分的处理) 

你可能感兴趣的:(算法,c++,leetcode)