系列文章目录
【三大基础查找!】顺序、二分、分块查找
目录
前言
查找和排序是数据结构与算法中不可或缺的一环,是前辈们在算法道路上留下的重要且方便的一些技巧,学习这些经典的查找和排序也能让我们更好和更快的解决问题。在这个专栏中我们会学习六大查找和十大排序,而本篇将详细讲解其中的三大经典查找——跳跃查找、斐波那契查找、插值查找
一、跳跃查找
1.使用场景
- 当数组有序时,可以使用跳跃查找减少比较的次数,它的查找效率介于顺序查找和二分查找之间,时间复杂度是O(
);
- 它相对于二分查找而言,二分查找在寻找最大或最小数据的时候需要回溯(多次回到区间里去找)很多次,而跳跃查找回溯只需要回溯一次(因为待查的区间已经确定了);
2.执行步骤
- 假设步长m,在数组中固定步长的往前跳,即arr[0] arr[m] arr[2m] arr[3m]...
- 在最坏的情况下,如果最后检查的值大于要查找的元素,必须跳 n/m 次,然后再执行线性查找 m-1 次。因此最坏情况下的比较总数为((n/m) + m-1);
- 当m =√n时,函数((n/m) + m-1)的值最小。因此,最佳步长为m =√n 即数组长度的平方根;
以数组{ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610 }为例,想要找到8所在的下标:
第一步:根据数学关系我们可以得出步长 m = 4 ;
第二步:比较当前下标index = 0时,arr[0] = 0 < 8,于是index += m,继续查找;
第三步:比较当前下标index = 4时,arr[4] = 3 < 8,于是index += m,继续查找;
第四步:比较当前下标index = 8时,arr[8] = 21 > 8,说明待查值小于往后的区间,开始回溯;
即目标区间是 【1*m,2*m】;
接下来只需要在目标区间中顺序查找就行了;
源码(不够成熟,仅供参考
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
//跳跃查找
int jumpSearch(int a[], int n, int key)
{
//在最坏的情况下,如果最后检查的值大于要查找的元素,必须跳 n/m 次,然后再执行线性查找 m-1 次。因此最坏情况下的比较总数为((n/m) + m-1)。
//当m =√n时,函数((n/m) + m-1)的值最小。因此,最佳步长为m =√n 即数组长度的平方根
int m = (int)sqrt(n);
//锁定区间
int prev = 0;
int min = (m < n) ? m : n;
while(a[min - 1]