一、顺序查找
顺序查找又叫线性查找法,是将数据一项一项地按顺序逐个查找,不管数据顺序如何,都得从头到尾遍历一次(在抽屉中逐层查找东西,也是顺序查找的应用)。
优点:文件在查找前不需要进行任何处理和排序
缺点:查找速度慢,适用于小数据文件的查找
代码实现:
public class Test3 {
public static void main(String[] args) {
//线性查找 linearSearch
/*
最好情况 查1, 1次就出来
最坏情况 查3, 9次出来
当数组长度越大的话,最坏情况就越差
时间复杂度(最坏情况) O(n)线性阶
*/
int[] arr ={1,2,4,12,7,6,5,9,3};
int key=9;//要找的数
int index=-1;//-1意味着找不到
for (int i=0;i<arr.length;i++){
if (arr[i]==key){
index=i;
break;
}
}
System.out.println(index);
}
}
二、二分查找
二分查找的数据事先已经排好序了,二分查找法是将数据分割成两等份,再比较键值与中间值的大小,如果键值小于中间值,可确定要查找的数据在前半部分,否则在后半部分,直到找到或不确定为止。
举个栗子:
已排序好的数组:2 3 5 8 9 11 12 16 18 键值:11
(1)首先和中值比较,与第五个值9比较,如下图所示:
(2)因为11>9,所以再和后半部分的中间值12比较,如下图所示
(3)因为11<12,所以和前半部分中间值11比较,如下图所示:
(4)因为11=11,查找结束
代码实现:
public class Test3 {
public static void main(String[] args) {
//二分查找 binarySearch 前提 数组必须有序
/*
最好情况 查46 1次就出来了
最坏情况 查12/60 O(logn)
*/
int[] arr1={12,17,21,32,38,41,46,49,50,50,51,59,60};
int key1=46;
int index1=-1;
int min_index=0;
int max_index=arr1.length-1;
int mid_index=(min_index+max_index)/2;
while(arr1[mid_index]!=key1){
if(key1<arr1[mid_index]){
max_index=mid_index-1;
}
if(arr1[mid_index]<key1){
min_index=mid_index+1;
}
if(min_index>max_index){
index1=-1;
break;
}
mid_index=(min_index+max_index)/2;
}
System.out.println(mid_index);
}
}
三、插值查找
插值查找又称插补查找,是二分查找的改进版。它是按照数据位置的分布,利用公式预测数据所在的位置,再以二分法的方式渐渐逼近。使用插值法的前提是假设数据平均的分布在数组中,而每一项数据的差距相当接近或有一定的距离比例。插值法的公式为:
其中key是要查找的值,data[high]、data[low]是剩余待查找记录中的最大值和最小值,假设数据项数为n,其步骤如下:
- 将记录由小到大的顺序设置为1,2,3,....n的编号
- 令low=1,high=n
- 当low<high时,重复执行4和5
- 令
- 若key<keymid且high不等于Mid-1,则令high=Mid-1
- 若key=keymid表示成功寻找键值的位置
- 若key>keymid且high不等于Mid-1,则令low=Mid+1.
注意:一般来说,插值寻找法优于顺序查找法,而如果数据的分布越平均,则查找速度越快,时间复杂度取决于数据分布的情况而定。
四、斐波那契查找
斐波那契查找法与二分法一样都是以分割范围来进行查找,不同的是斐波那契查找法不是对半分割,而是以斐波那契级数的方式来分割。
斐波那契级数:0,1,1,2,3,5,8,13,21,34,55,89....除了第0个和第1个元素外,级数中的每个值都是前两个值得和。
斐波那契查找法是以斐波那契树来寻找数据,如果数据的个数为n,而且n比某一个斐波那契数小,满足该表达式:Fib(k+1)≥n+1.
public static int fibonacciSearch(int[] lookupTable,int[] f,int target){
int low = 0;
int high = lookupTable.length - 1;
int k = 0;// k 是 Fibonacci 分割数组下标
int middle = 0;
while (f[k] < high){
k ++;
}
int[] temp = Arrays.copyOf(lookupTable,f[k]);
while (low <= high){
middle = low + f[k - 1];
if (target < lookupTable[middle]){
high = middle -1;
k --;
}else if (target > lookupTable[middle]){
low = middle + 1;
k -= 2;
}else{
return middle < high ? middle : high;
}
}
return -1;
}