查找算法之四 斐波那契查找(C++版本)

算法介绍:
斐波那契搜索就是在二分查找的基础上根据斐波那契数列进行分割的。在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为Fn,完成后进行斐波那契分割,即F[n]个元素分割为前半部分F[n-1]个元素,后半部分F[n-2]个元素,找出要查找的元素在那一部分并递归,直到找到。

查找步骤:
同二分查找

注意事项:
为什么需要将临时数组的长度设置为F(k) - 1,看下图:
在这里插入图片描述
数组长度为F(k) - 1;
左区间长度为F(k - 1) - 1;
右区间长度为F(k - 2) - 1;
middle节点只有一个,长度为1
因为公式成立:
F(k) - 1 = F(k - 1) + F(k - 2)
所以下面公式也成立:
F(k) - 1 = F(k - 1) - 1 + 1 + F(k - 2) - 1

F(k) - 1 = (F(k - 1) - 1)(左区间元素个数) + 1(middle元素个数) + (F(k - 2) - 1)(右区间元素个数)

实现代码:

// 获取fibonacci数列

void GetFibonacciArray(int* pData, int destIdx)
{
	if (nullptr == pData || destIdx < 2) return;
	
	pData[0] = 1;
	pData[1] = 1;
	for (int idx = 2; idx < destIdx; ++idx) pData[idx] = pData[idx - 1] + pData[idx - 2];
}

int FibonacciSearch(int* pData, int size, int value)
{
	if (nullptr == pData || size < 1) return -1;

	// 构造fibonacci数组
	const int FIBONACCI_MAX_IDX = 20;
	int* pFibData = new int[FIBONACCI_MAX_IDX];
	GetFibonacciArray(pFibData, FIBONACCI_MAX_IDX);

	// 获取第一个大于等于size + 1的fibonacci数, 或许写成pFibData[destIdx] < size + 1更加清晰些
	int destIdx = 0;
	while (pFibData[destIdx] - 1 < size) ++destIdx;

	// 构造临时数组,元素个数为pFibData[destIdx] - 1, 为了使用fibonacci算法,将临时数组长度扩充至pFibData[destIdx] - 1
	int* pTempData = new int[pFibData[destIdx] - 1];

	// 将pData中的数据复制到pTempData(原本空间)
	memcpy(pTempData, pData, size * sizeof(int));

	// pTempData剩余的空间(扩充空间)用pData中最后一个值进行赋值
	for (int idx = size; idx < pFibData[destIdx] - 1; ++idx) pTempData[idx] = pData[size - 1]; 

	int left = 0;
	int right = size - 1;

	while (left <= right)
	{
		int middle = left + pFibData[destIdx - 1] - 1; 
		if (value == pTempData[middle]) // 找到
		{
			if (middle < size) return middle; // 元素位于原本空间中,直接返回下标
			else return size - 1; // 元素位于扩充空间,因为扩充空间都是用pData[size - 1]进行的赋值,所以返回下标size - 1
		}
		else if (value > pTempData[middle]) // 右区间查找
		{
			left = middle + 1;
			destIdx = destIdx - 2;
		}
		else // 左区间查找
		{
			right = middle - 1;
			destIdx = destIdx - 1;
		}
	}

	delete [] pTempData;
	delete [] pFibData;
	
	return -1;
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值