《編程珠璣》之二分搜索

chapter4 + chapter5 書中的觀點:

@1,程序員都是樂觀主義者,他們總是試圖走捷徑;編寫函數代碼,並將其插入系統中,然後熱切的期望它能運行。有時候這樣行的通,但是有千分之九百九十九的概率,這樣做會導致一場災難!

@2,專業的程序員永遠不會忘記,無論系統的行爲咋看起來多麼的神祕莫測,其背後總有合乎邏輯的解釋。

@3,雖然第一篇關於二分搜索的論文在1946年就發表了,但是第一個沒有錯誤的二分搜索程序卻直到1962年纔出現。

@4,關鍵詞:“連續兩輪僅首次運行正確”,函數調用的前置條件和後置條件,“契約編程” . 

 

        作者用兩章的篇幅,介紹了編寫 “正確” 程序的方法。包括從理論上(數學)層面證明二分搜索的正確性,用腳手架驗證程序,用斷言快速定位程序不合理的邏輯及變量值。

a,二分搜索的數學層面證明,對於已經升序排序的數組序列 a[b,e];找出 T 在a數組中的位置。m = (b+e)/2 ,如果 a[m] > T,那麼 T 必然不在 a[m+1,e]  序列中; 如果 a[m] < T,那麼 T 必然不在a[b,m-1] 序列中。因此每次比較,均可對查找的範圍減半。

b,程序正確性驗證的方法 ,以下面的程序爲例:

        a,程序能否正常終止: 當輸入  9 40  時,程序會陷入死循環! 爲什麼 b = mid +1,  e = mid -1 ;已經對每次的循環都保證縮小1,還是免不了死循環?問題在於,第二次循環 b=5, mid=9, e=8;這本來就是不合理的,mid值跑到 [b,e] 範圍之外去了(這也可以作爲斷言的條件)。當 mid - 1 正好等於 8,因此下次計算mid時,還是  b=5, mid=9, e=8. 

       b,修正a的問題,將 mid = b + e/2  改成  mid = b + (e-b)/2.    繼續測試。按常見的錯誤,將 b= mid +1 改成 b = mid ;  將 e = mid -1 改成 e = mid;繼續驗證。當 輸入 0  -1;0  0;0  5;1  0;均能正常工作,輸入 1  5 時,程序又進入死循環。不難分析 b = 0, mid = 0,e = 0;下一次循環還是  b = 0, mid = 0,e = 0;問題是,每次循環,查找的範圍沒有保證至少縮小1個位置範圍。

 #include<stdio.h>
#include<assert.h>
int binarySearch(int arr[], int size, int value)
{
    assert(size >= 0);
    if(0==size)
    {
        return -1;
    }
    int b = 0;
    int e = size - 1;
    while(e >= b)
    {
        int mid = b + e/2;
        assert(mid >= 0 && mid < size);   //斷言對於快速定位問題很有幫助
        printf("b:%d, mid:%d, e:%d\n",b,mid,e);  //有時在大型程序中,添加rintf打印調試,是個sample but powerful 的方法
        if(value > arr[mid])
            b = mid + 1;
        else if(value < arr[mid])
            e = mid - 1;
        else
            return mid;
    }
    return -1;
}


int main()
{
    //簡單測試
    int s[10];
    for(int i=0;i<10;++i)
    {
        s[i]=5*i;
        printf("%d ",s[i]);
    }
    printf("\n");

    int n,v;
    //注意對邊界情況做測試,一般能快速發現程序問題
    scanf("%d %d",&n,&v);
    while(n>=0 && n<=10)
    {
        printf("n:%d, v:%d \n",n,v);
        printf("index:%d\n",binarySearch(s,n,v));
        scanf("%d %d",&n,&v);
    }

    return 0;
}
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章