二分查找及其变种
一、二分查找
二分查找算法又称折半查找算法。
其算法的基本思想是:在有序表中,取中间的记录作为比较关键字,若给定值与中间记录的关键字相等,则查找成功;若给定的值小于中间记录的关键字,则在中间记录的左半区间继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区间继续查找;不断重复这个过程,直到查找成功。否则查找失败。
code:
1 public int binarySearch(int[] a,int key) { 2 int low = 0; 3 int high = a.length - 1; 4 int mid = 0; 5 while(low <= high){ 6 mid = (low + high) / 2; 7 if(a[mid] == key) return mid; 8 if(a[mid] > key) high = mid - 1; 9 if(a[mid] < key) low = mid + 1; 10 } 11 return -1; 12 }
二、二分查找算法的变种
1. 插值查找算法
由于二分查找的mid 每一次都是取中间的那个节点,这样效率不是很高,比如有0-1000000,有1000000个节点,要查找10,这样就会导致查找很多次,所以有人提出了插值查找算法。说白了就是改变划分的比例,比如三分或者四分。
其计算公式如下:
插值查找算法:
mid=low+(key−a[low]) / (a[high]−key) *(high−low)
二分查找算法:
mid=low+ 1/2 * (high−low)
2. 斐波那契查找算法
斐波那契被递归方法如下定义:F(1)=1,F(2)=1,F(n)=f(n-1)+F(n-2) (n>=2)。1、1、2、3、5、8、13、21、····。
斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的。
在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为F[n](如果要补充元素,则补充重复最后一个元素,直到满足F[n]个元素),
完成后进行斐波那契分割,即F[n]个元素分割为前半部分F[n-1]个元素,后半部分F[n-2]个元素,找出要查找的元素在那一部分并递归,直到找到。
斐波那契查找的时间复杂度还是O(log 2 n ),但是 与折半查找相比,斐波那契查找的优点是它只涉及加法和减法运算,而不用除法,而除法比加减法要占用更多的时间,
因此,斐波那契查找的运行时间理论上比折半查找小,但是还是得视具体情况而定。
对于斐波那契数列:1、1、2、3、5、8、13、21、34、55、89……(也可以从0开始),前后两个数字的比值随着数列的增加,越来越接近黄金比值0.618。比如这里的89,把它想象成整个有序表的元素个数,而89是由前面的两个斐波那契数34和55相加之后的和,也就是说把元素个数为89的有序表分成由前55个数据元素组成的前半段和由后34个数据元素组成的后半段,那么前半段元素个数和整个有序表长度的比值就接近黄金比值0.618,假如要查找的元素在前半段,那么继续按照斐波那契数列来看,55 = 34 + 21,所以继续把前半段分成前34个数据元素的前半段和后21个元素的后半段,继续查找,如此反复,直到查找成功或失败,这样就把斐波那契数列应用到查找算法中了。