二分搜索算法正确性判别

问题描述:

        下面7个算法与本章中的二分搜索算法BinarySearch略有不同。请判断这7个算法的正确性,不正确则给出理由。

具体分析:

template<class Type>
int BinarySearch1(Type a[], const Type& x, int n){
    int left = 0;
    int right = n-1;
    while(left <= right){
        int middle = (left + right) / 2;
        if(x == a[middle])
            return middle;
        if(x > a[middle])
            left = middle;
        else
            right = middle;
    }
    return -1;
}

(1).该算法中left的更新值为middle,如果一开始搜索的就是a[n - 1],即x = a[n - 1],那么由于除法的向下取整,会使代码陷入死循环,因此错误。

template<class Type>
int BinarySearch2(Type a[], const Type& x, int n){
    int left = 0;
    int right = n-1;
    while(left < right - 1){
        int middle = (left + right) / 2;
        if(x < a[middle])
            right = middle;
        else
            left = middle;
    }
    if(x == a[left])
        return left;
    else
    	return -1;
}

(2).这个算法由于循环条件是left < right - 1,所以并不会出现上述死循环情况,因为当left == right - 1时循环就结束了,但是该算法将搜索成功的判定交给left变量来做,姑且称之为由left负责判定,也正因为这个循环条件,left永远取不到(n-1)这个值,这意味着当x = a[n - 1]时,会错误地返回-1,而不是(n-1)。

template<class Type>
int BinarySearch3(Type a[], const Type& x, int n){
    int left = 0;
    int right = n-1;
    while(left + 1 != right){
        int middle = (left + right) / 2;
        if(x >= a[middle])
            left = middle;
        else
            right = middle;
    }
    if(x == a[left])
        return left;
    else
    	return -1;
}

(3).算法3其实与算法2基本等价,因为循环条件是等价的,left和right两个变量的赋值也是等价的,也是由变量left负责判定,所以当x = a[n - 1]时,就会错误地返回-1,而不是(n-1)。

template<class Type>
int BinarySearch4(Type a[], const Type& x, int n){
    if(n > 0 && x >= a[0]){
   		int left = 0;
    	int right = n-1;
    	while(left < right){
        	int middle = (left + right) / 2;
        	if(x < a[middle])
            	right = middle - 1;
        	else
            	left = middle;
    	}
    	if(x == a[left])
        	return left;
    }
    return -1;
}

(4).算法4在前面的基础上添加了一点输入规范性的检查,还有一个大的改变就是right的更新值变成了middle - 1,left的更新值则不变,前面提到过由于middle的计算是向下取整,当搜索x = a[n - 1]时,会让代码陷入死循环,因此错误。

template<class Type>
int BinarySearch5(Type a[], const Type& x, int n){
    if(n > 0 && x >= a[0]){
   		int left = 0;
    	int right = n-1;
    	while(left < right){
        	int middle = (left + right + 1) / 2;
        	if(x < a[middle])
            	right = middle - 1;
        	else
            	left = middle;
    	}
    	if(x == a[left])
        	return left;
    }
    return -1;
}

(5).算法5既不会出现前面提到的陷入死循环情况,也不会出现返回值错误的情况,因此正确。

template<class Type>
int BinarySearch6(Type a[], const Type& x, int n){
    if(n > 0 && x >= a[0]){
   		int left = 0;
    	int right = n-1;
    	while(left < right){
        	int middle = (left + right + 1) / 2;
        	if(x < a[middle])
            	right = middle - 1;
        	else
            	left = middle + 1;
    	}
    	if(x == a[left])
        	return left;
    }
    return -1;
}

(6).算法6在5的基础上,将middle的计算改为向上取整,并且left的更新值改为middle + 1,可以看到该算法由left负责判定,如果我们第一次计算出的middle对应的a[middle]就是我们要搜索的数值,那么该算法会错误地返回-1,因此错误。

template<class Type>
int BinarySearch7(Type a[], const Type& x, int n){
    if(n > 0 && x >= a[0]){
   		int left = 0;
    	int right = n-1;
    	while(left < right){
        	int middle = (left + right + 1) / 2;
        	if(x < a[middle])
            	right = middle;
        	else
            	left = middle;
    	}
    	if(x == a[left])
        	return left;
    }
    return -1;
}

(7).算法7与6的区别是将left和right两个变量的更新值都改为了middle,这种方式与算法1很相似,当我们要搜索的值x = a[0]时,该算法也同样会陷入死循环。

粗略地总结以下几点规律:

1.当循环结束条件为left = right时可能会出现死循环的情况。

2.midddle的计算为向上取整时,right的更新值不能取middle;middle的计算为向下取整时,left的更新值不能取middle。否则可能会出现死循环。

3.负责判定的那个变量(left或者right)的更新值只能取middle,否则可能会出现返回值错误的情况。

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值