码迷,mamicode.com
首页 > 其他好文 > 详细

二分检索的多种应用

时间:2015-07-31 21:55:02      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:

其实,二分法真的不那么简单,尤其是二分法的各个变种。 最最简单的二分法,就是从一个排好序的数组之查找一个key值。 如下面的程序:
int search(int *arr, int n, int key)
{
    int left = 0, right = n-1;
    while(left<=right) {
        int mid = left + ((right - left) << 1);
        if (arr[mid] == key) return mid; 
        else if(arr[mid] > key) right = mid - 1;
        else left = mid + 1;
    }
    return -1;
}
这个程序,相信只要是一个合格的程序员应该都会写。 稍微注意一点, 每次移动left和right指针的时候,需要在mid的基础上+1或者-1, 防止出现死循环, 程序也就能够正确的运行。

但如果条件稍微变化一下, 你还会写吗?如,数组之中的数据可能可以重复,要求返回匹配的数据的最小(或最大)的下标;更近一步, 需要找出数组中第一个大于key的元素(也就是最小的大于key的元素的)下标,等等。 这些,虽然只有一点点的变化,实现的时候确实要更加的细心。 下面列出了这些二分检索变种的实现。

1. 找出第一个与key相等的元素

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

2. 找出最后一个与key相等的元素

int searchLastEqual(int *arr, int n, int key)
{
    int left = 0, right = n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] > key) right = mid - 1;
        else if(arr[mid] <= key) left = mid + 1; 
    }
    if( right>=0 && arr[right] == key) return right;
    return -1;
}
3. 查找第一个等于或者大于Key的元素

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

4. 查找第一个大于key的元素

int searchFirstLarger(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] > key) right = mid-1;
        else if (arr[mid] <= key) left = mid+1;
    }
    return left;
}
5. 查找最后一个等于或者小于key的元素
int searchLastEqualOrSmaller(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int m = (left+right)/2;
        if(arr[m] > key) right = m-1;
        else if (arr[m] <= key) left = m+1;
    }
    return right;
}
6. 查找最后一个小于key的元素

int searchLastSmaller(int *arr, int n, int key)
{
    int left=0, right=n-1;
    while(left<=right) {
        int mid = (left+right)/2;
        if(arr[mid] >= key) right = mid-1;
        else if (arr[mid] < key) left = mid+1;
    }
    return right;
}
很多的时候,应用二分检索的地方都不是直接的查找和key相等的元素,而是使用上面提到的二分检索的各个变种,熟练掌握了这些变种,当你再次使用二分检索的检索的时候就会感觉的更加的得心应手了。



版权声明:本文为博主原创文章,未经博主允许不得转载。

二分检索的多种应用

标签:

原文地址:http://blog.csdn.net/gui951753/article/details/47175771

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!