各種缺陷的二分法演算法

來源:互聯網
上載者:User

二分法是思想精髓就是如果左下標和右下標得到的中間下標所在的值等於所要尋找的值,演算法結束;如果中間的值小於目標值,則說明目標值可能在中間值和右下標所在的區間內,就將中間下標當成左下標,繼續搜尋。如果中間值大於目標值,則把中間下標當成右下標,繼續搜尋。

這是近期在網上用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的情況,否則一定會訪問越界。

int bsearch(int* a, int l, int r,int k)<br />{<br /> int mid = 0;<br /> if(l-r == 0)<br /> return -1;<br /> while(l<=r){<br /> mid = (l+r)/2;<br /> if(a[mid]<k) l = mid+1;<br /> else if(a[mid]>k) r=mid-1;<br /> else return mid;<br /> }<br /> return -1;<br />}<br />

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.