1 二分查找
在有序表中,取中间记录作为比较对象,将其与给定值相比较,若其等于给定值,则查找成功;若其小于给定值,则在中间记录的右半区继续查找;若其大于给定值,则在中间记录的左半区继续查找。不断重复以上过程,直到查找成功或无匹配记录。
使用该查找方法的前提条件在于,线性表中的数据必须有序,且必须采用顺序存储的方式。
var array = [1,2,3,4,5,6,7,8,9]
function search(value){
let low = 0, high = array.length - 1;
let mid;
while (low <= high){
mid = parseInt((low + high)/2);
if (array[mid] > value){
high = mid - 1;
}else if (array[mid] < value){
low = mid + 1;
}else{
break;
}
}
if (array[mid] === value) return mid;
return -1;
}
console.log('查找3',search(3));
console.log('查找8',search(8));
console.log('查找10',search(10));
2 插值查找
插值查找与二分查找的原理类似,区别就在于mid值的选取。
在插值查找中,mid = low + ( (key - a[low]) / (a[high] - a[low]) ) * (high - low)
。该算法对表长较大,而关键字分布比较均匀的情况下,性能较高,而对于分布不均匀的数据,则不太适用。
var array = [1,2,3,4,5,6,7,8,9]
function search(value){
let low = 0, high = array.length - 1;
let mid;
while (low <= high){
mid = parseInt( low + (value-array[low]) / (array[high]-array[low]) * (high - low) );
if (array[mid] > value){
high = mid - 1;
}else if (array[mid] < value){
low = mid + 1;
}else{
break;
}
}
if (array[mid] === value) return mid;
return -1;
}
3斐波那契查找
顾名思义,该查找方法利用了斐波那契数列,该方法的主要思路为,先在斐波那契数列F中找到第k
项,使其满足,F[k]-1 > 有序数组的最大索引号 > F[k-1]-1
,然后将数组扩充到长度为F[K]-1
,并使扩充项的值都等于有序数组的最后一项。
分割点的索引为mid = low + F[K-1]-1
,此时有序数组被mid划分为两段,左段长度为F[K-1]-1
,右段长度为F[k-2]-1
。若查找值大于mid值,则low等于mid+1,而k = k - 2;若查找值小于mid,则high = mid -1,k =k -1.
var array = [1,2,3,4,5,6,7,8,9]
var F = [0,1,1,2,3,5,8,13,21,34]
function search(value){
let low = 0, high = array.length - 1,n= array.length - 1;
let mid,k=0;
while (high > F[k]-1){ //寻找第k项
k++;
}
for (let i=high; i<F[k]-1; i++){ //补全有序数组
array[i] = array[high];
}
while (low <= high){
mid = low + F[k-1] -1;
if (array[mid] > value){
high = mid - 1;
k -= 1; //长度缩减为 F[k-1] -1
}else if (array[mid] < value){
low = mid + 1;
k -= 2; //长度缩减为 F[k-2] -1
}else{
if (mid <= n) //相等则找到位置
return mid;
else //大于原始长度,则说明等于数组最后一项
return n;
}
}
return -1;
}