各种缺陷的二分法算法

76 篇文章 0 订阅
57 篇文章 0 订阅

二分法是思想精髓就是如果左下标和右下标得到的中间下标所在的值等于所要查找的值,算法结束;如果中间的值小于目标值,则说明目标值可能在中间值和右下标所在的区间内,就将中间下标当成左下标,继续搜索。如果中间值大于目标值,则把中间下标当成右下标,继续搜索。

这是近期在网上用google搜索“二分法算法”找到的二分法算法。结果发现各种各样的缺陷。

public int erfen()
//二分法查找
{
int iindex=0; //相当于指针的东西
int istart=0; //
int iend=iarray.length-1;
while(true)
{
icount++;
iindex = (istart+iend)/2;
if(iarray[iindex]<iseek)
{
istart = iindex;
}
else if(iarray[iindex]>iseek)
{
iend = iindex;
}
else
{
break;
}
}
return icount;

 用一个测试用例就能证明的这个算法错误。

0 1 2 3 4 5查找5.结果你会发现死循环。

很多人认为只要起始值的左值和右值相加为n-1就可以了。其实不然,二分法是10年多的时间才找到了一种正确的算法。如果你开始的左值设为0并且右值设为n-1,程序很大的程度上会错。除非你解决了最后的死循环问题。

下面的算法

 

left  =   - 1 ;

right 
=  length;

while (left  <=  right)

{
     mid 
=  (left  +  right) / 2 ;
     
if (a[mid]  >  value)

     
{
        
// 中间值比目标值大  
        right  =  mid;
     }

     
else   if (a[mid]  <  value )
     
{
            
// 中间值比目标值小
            left  =  mid;
      }

      
else
      
{
          
// 找到,中间值等于目标值
           return  left;
      }


}

return   - 1 ;

可以解决上面的0 1 2 3 4 5 查找5找不到的问题。但是,却在查找不存在的数上出了问题。比如6

下面的代码解决了这个问题:

 

left  =   - 1 ;

right 
=  length;

while (left  + 1   !=  right) // 注意这句话!!!

...
{
     mid 
=  (left  +  right) / 2 ;
     
if (a[mid]  >  value)

     ...
{
        
// 中间值比目标值大  
        right  =  mid;
     }

     
else   if (a[mid]  <  value )
     ...
{
            
// 中间值比目标值小
            left  =  mid;
      }

      
else
      ...
{
          
// 找到,中间值等于目标值
           return  left;
      }


}

return   - 1 ;

但是上的这段真的解决了所有的问题?如果left + right 超过了整数范围?

改为下面的代码:

 

int  BinarySearch( int  value)
{
    
  

    
int  left  =  -1 ;
    
int  right  =  length ;
    
int  mid;
    
while (left +1! =  right)
    
{
        mid 
=  left  + (right - left) / 2 ; // 注意这里的写法
         if (values[mid]  ==  value)
        
{
            
return  mid;
        }

        
else   if (values[mid]  <  value)
        
{
            left 
=  mid;
        }

        
else
        
{
            right 
=  mid;
        }

    }

    
return   - 1 ;
    
}

这里解决了越界问题。但是这段代码真的没有问题了吗?没有人能保证。除非能用数学证明。

另外还有一种写法:但是必须特判length==0的情况,否则一定会访问越界。

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
二分法(二分查找)是一种在有序数组中查找某一特定元素的搜索算法。实现的基本思路是将数组从中间开始分成两部分,判断要查找的元素在哪一部分中,然后继续在该部分中进行查找,直到找到目标元素或者确定目标元素不存在为止。 下面是用 Java 实现二分法算法的示例代码: ```java public class BinarySearch { // 二分法查找指定元素在数组中的位置 public static int binarySearch(int[] arr, int target) { int left = 0; int right = arr.length - 1; while (left <= right) { int mid = (left + right) / 2; if (arr[mid] == target) { return mid; } else if (arr[mid] < target) { left = mid + 1; } else { right = mid - 1; } } return -1; } // 测试二分法算法 public static void main(String[] args) { int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9}; int target = 5; int result = binarySearch(arr, target); if (result == -1) { System.out.println("元素不在数组中"); } else { System.out.println("元素在数组中的位置为:" + result); } } } ``` 在这个示例代码中,我们定义了一个 `binarySearch` 方法来实现二分法算法。该方法接收两个参数:一个有序数组和一个目标元素。在方法中,我们定义了两个变量 `left` 和 `right` 分别表示数组的左右边界。然后使用一个 while 循环来不断缩小查找范围,直到找到目标元素或者确定目标元素不存在为止。 在循环中,我们首先计算出数组的中间位置 `mid`,然后判断目标元素是在中间位置的左边还是右边。如果目标元素比中间位置的值要大,则说明目标元素在中间位置的右边,需要将左边界向右移动;反之,如果目标元素比中间位置的值要小,则说明目标元素在中间位置的左边,需要将右边界向左移动。当左边界大于右边界时,表示目标元素不存在于数组中,此时返回 -1。 最后,我们在 `main` 方法中调用 `binarySearch` 方法来测试二分法算法。在测试中,我们定义了一个有序数组和一个目标元素,并将它们作为参数传递给 `binarySearch` 方法。如果方法返回的结果为 -1,则表示目标元素不在数组中;否则,方法返回的结果就是目标元素在数组中的位置。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值