循环不变量
“int l = 0, r = n - 1; // 在[l…r]的范围里寻找target”中,对于l和r的定义是全局不变的,一旦定义确定了,它们的取值也就确定了,分别为l=0和r=n-1。
另一种定义方式及对应的初始值:
“int l = 0, r = n; // target在[l…r)的范围里”,对应初始值l=0,r=n。
二分搜索法代码:
#include <iostream>
#include <cmath>
#include <cassert>
#include <ctime>
#include "util.h"
using namespace std;
template<typename T>
int binarySearch(T arr[], int n, T target){
int l = 0, r = n - 1; // 在[l...r]的范围里寻找target
while(l <= r){ // 当 l == r时,区间[l...r]依然是有效的
int mid = l + (r - l) / 2;
if(arr[mid] == target) return mid;
if(target > arr[mid])
l = mid + 1; // target在[mid+1...r]中; [l...mid]一定没有target
else // target < arr[mid]
r = mid - 1; // target在[l...mid-1]中; [mid...r]一定没有target
}
return -1;
}
/*另一种对循环不变量的定义方式所对应的写法:
int binarySearch(T arr[], int n, T target){
int l = 0, r = n; // target在[l...r)的范围里
while(l < r){ // 当 l == r 时, 区间[l...r)是一个无效区间
int mid = l + (r - l) / 2;
if(arr[mid] == target) return mid;
if(target > arr[mid])
l = mid + 1; // target在[mid+1...r)中; [l...mid]一定没有target
else// target < arr[mid]
r = mid; // target在[l...mid)中; [mid...r)一定没有target
}
*/
int main() {
int n = pow(10, 7);
int* data = MyUtil::generateOrderedArray(n);
clock_t startTime = clock();
for(int i = 0 ; i < n ; i ++)
assert(i == binarySearch(data, n, i));
clock_t endTime = clock();
cout << "Binary Search test complete." << endl;
cout << "Time cost: " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
return 0;
}
求mid的改进
mid = l + (r - l) / 2
避免了由mid=l+r可能引起的溢出问题。