ckook

导航

 

一个整数数组A[n]已排序,在数组中查找一个值为val的数,若存在则返回该数在数组中的位置k,有以下四个问题:

1. 数组由小到大排列时,要求k最靠左

2. 数组由小到大排列时,要求k最靠右

3. 数组由大到小排列时,要求k最靠左

4. 数组由大到小排列时,要求k最靠右

 

这四个问题用线性扫描搜索解决很简单,但如果用二分法如何正确的搜索呢?以下给出这四个问题的解答,注意差异,感兴趣的读者可以自己分析一下为什么会有这些差异。

int binsearch_leftmost_asc(int key, int arr[], int len)
{
    int left = 0;
    int right = len - 1;
    int mid;
    while(left <= right) {
        //不用(left + right)/2 以免计算left+right时溢出
        mid = left + (right - left) / 2; //向左取整
        if(key > arr[mid]) left = mid + 1;
        else right = mid - 1;
    }
    if(key == arr[left]) return left;
    return -1;
}

int binsearch_leftmost_asc(int key, int arr[], int len)
{
    int left = 0;
    int right = len - 1;
    int mid;
    while(left < right) { //注意微妙差异
        mid = left + (right - left) / 2;
        if(key > arr[mid]) left = mid + 1;
        else right = mid;
    }
    if(key == arr[left]) return left;
    return -1;
}

int binsearch_leftmost_desc(int key, int arr[], int len)
{
    int left = 0;
    int right = len - 1;
    int mid;
    while(left <= right) {
        mid = left + (right - left) / 2;
        if(key < arr[mid]) left = mid + 1;
        else right = mid - 1;
    }
    if(key == arr[left]) return left;
    return -1;
}

int binsearch_rightmost_asc(int key, int arr[], int len)
{
    int left = 0;
    int right = len - 1;
    int mid;
    while(left < right) {
        mid = left + (right - left + 1) / 2; //向右取整
        if(key < arr[mid]) right = mid - 1;
        else left = mid;
    }
    if(key == arr[left]) return left;
    return -1;
}

int binsearch_rightmost_desc(int key, int arr[], int len)
{
    int left = 0;
    int right = len - 1;
    int mid;
    while(left < right) {
        mid = left + (right - left + 1) / 2;
        if(key > arr[mid]) right = mid - 1;
        else left = mid;
    }
    if(key == arr[left]) return left;
    return -1;
}

 

posted on 2012-05-29 18:57  ckook  阅读(553)  评论(0)    收藏  举报