查找法的疑惑

想用二分法查找数据,搜了半天,发现非递归的大概两种。(我不喜欢递归的,担心堆栈问题)

如下:

https://yq.aliyun.com/ziliao/12066


/*第一种方法,判断都在循环内*/
int binSearch(int x, int a[], int n)
{
   int low, high, mid;
   low = 0;
   high = n-1;
   //注意,这里必须用<=, 用<不对,一直返回-1
   while(low <= high)
   {
      mid = (low + high) / 2;
      if(x < a[mid])
      high = mid - 1;
      else if(x > a[mid])
      low = mid + 1;
      else
      return mid;
   }
   return -1;
}
/*在循环内执行一次测试的方法*/
/*int binSearch(int x, int a[], int n)
{
   int low, high, mid;
   low = 0;
   high = n-1;
   mid = (low + high) / 2;
   while((low <= high)&&(a[mid]!=x))
   {
      if(x < a[mid])
      high = mid -1;
      else
      low = mid + 1;
      mid = (low + high) / 2;
   }
   if(a[mid] == x)
   return mid;
   else
   return -1;
}
*/


在百度百科https://baike.baidu.com/item/%E4%BA%8C%E5%88%86%E6%B3%95%E6%9F%A5%E6%89%BE/9751511

有:

//非递归算法
int binary( int *a, int key, int n )
{
    int left = 0, right = n - 1, mid = 0;
    mid = ( left + right ) / 2;
    while( left < right && a[mid] != key )
    {
        if( a[mid] < key ) {
            left = mid + 1;
        else if( a[mid] > key ) {
            right = mid - 1;
        }
        mid = ( left + right ) / 2;
    }
    if( a[mid] == key )
        return mid;
    return -1;
}
int main()
{
    int a[] = {1,2,3,4,5,6,7,8,9,12,13,45,67,89,99,101,111,123,134,565,677};
    int b[] = {677,1,7,11,67};
    int i;
    for( i=0; i<sizeof(b)/sizeof(b[0]); i++ )
    {
        //printf( "%d\n", recurbinary(a, b[i],0,sizeof(a)/sizeof(a[0])-1) );
        printf"%d\n", binary( a, b[i], sizeof(a)/sizeof(a[0])));
    }
    return 0;
}
在第一个链接是 while((low <= high)&&(a[mid]!=x)),第二个链接是while( left < right && a[mid] != key )
看出来了吧,可能有个错误的。懒得查哪个错了。
于是就用第一个链接的第一种方法了。
int binSearch(int x, int a[], int n)
{
   int low, high, mid;
   low = 0;
   high = n-1;
   //注意,这里必须用<=, 用<不对,一直返回-1
   while(low <= high)
   {
      mid = (low + high) / 2;
      if(x < a[mid])
      high = mid - 1;
      else if(x > a[mid])
      low = mid + 1;
      else
      return mid;
   }
   return -1;
}


网上也有这么写的
int search(int aim,int data[],int size){    
    int det = -1;  
    int left = 0; 
    int right = size-1;
    while(left<=right){  
        int mid = (left+right)/2;
        if(data[mid]<aim){  
            left = mid+1;     
        }else if(data[mid]>aim){  
            right = mid-1;  
        }else{  
            det = mid;  
            break;  
        }  
    }  
    return det;  

这个实现是绝对没有问题的,网上也有好多地方就是这么写的。


我不喜欢用int,涉及到负数的东西比较不容易理解。于是将int 改成uint16_t  就是 无符号的16bit的。
结果运行出错,如果想查找的aim在 数组data中不存在,就直接进入了hartdefault里面了。就是说可能指令出问题或内存溢出之类的。
很奇怪!必须找到根源!
跟踪了一下,发现当mid=0的时候,right=mid-1就是0xFFFFFFFF,于是下一把进入循环0<0xFFFFFFFF就为真,那么就是data[0XFFFFFFFF]
就是指针溢出,直接不给机会,飞到了九霄云外了!
如果用int类型,那么0<0XFFFFFFFF就不成立,就直接进入return det了。
所以原因找到。
看样以后写代码不能直接把int改成别的了。还好,我有个好习惯,只要是别人的东西,我改了的话,都要验证一下。

根源还是c语言还是很容易出问题的。

真是个危险的函数!!!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值