代码调优--二分搜索
首先从一个问题引出下面的内容:如何确定增序的数组x[0...n-1]中整数t第一次出现的位置
1、之前博客中的设计简单并且易于维护的二分搜索效率已经很高,一般情况下不需要改变,但是对其进行调优可以获得不错的加速
2、之前的二分搜索寻找t的位置是随机的,并不一定是t出现的第一个位置
第一种算法(原理查看循环不变式说明):
1 int binarySearch2(int arr[], int n, int t){ 2 int l=-1, u=n, m; 3 while(l+1 != u){ 4 /* loop invariant: x[l] <t && x[u]>=t && l<u*/ 5 m = (l+u)/2; 6 if(arr[m] < t) 7 l = m; 8 else 9 u = m; 10 } 11 // assert(l+1 == u && x[l]<u && x[u]>=t) 12 if(u == n || arr[u] != t) 13 return -1; 14 return u; 15 }
由于每次循环中:在每次循环迭代中,他只对t和x中的元素做一次比较,而原先的程序却可能必须比较两次,因此效率增加,并且解决的是比原先的更加复杂的问题(寻找数组中第一次出现的位置)
第二种算法:我们这里假设n = 1000这个条件,即向量的大小为1000
我们不使用l...u来表示上下限值,而是使用下限值 l 和以及增量i来表示,使得l+i == u。程序代码将确保i为2的幂;可以初始化l为-1,i为最大的使得l+i < 1000的值,这里就初始化i为512。这样 l 和 l+i要么一起表示-1...511,要么一起表示488....512,这个表示范围是为了满足同上一个算法的循环不变式在初始化时满足,通过判断x[511]与t的大小来确定选取哪个范围。
1 int binarySearch3(int arr[], int t){ 2 int i=512, l=-1; 3 if(arr[l+i] < t) 4 l = 1000 - 512; 5 while(i != 1){ 6 // loop invarient: x[l] < t && x[l+i] >=t && i为2的幂 7 i = i/2; 8 if(arr[l+i] < t) 9 l = l+i; 10 } 11 //assert(i == 1 && x[l] < t && x[l+1] >= t) 12 if(l+1 == 1000 || arr[l+1] > t) 13 return -1; 14 //assert(x[l+1] == t && x[l] < t) 15 return l+1; 16 }