lower_bound upper_bound的简单实现(STL)

参考文章:L_J_SHOU CobbLiu


1. lower_bound 指的是 返回第一个 ”大于等于 value“ 的元素位置。

    另一种解释是 可插入”元素值为 value“且 ”不破坏有序性“的 第一个 位置

2. upper_bound 指的是 返回第一个 “大于 value ” 的元素位置;

    另一种解释是 可插入”元素值为 value“且 ”不破坏有序性“的 最后一个 位置

举个例子: 1 2 2 3 4 5

value = 2: 则 lower_bound 返回的位置是 第 1 个位置;(从第0个位置开始)

                        upper_bound 返回的位置是 第 3 个位置。

大家可以看到一个很有意思的性质:

upper_bound - lower_bound = 数组中 value 的个数

下面我们来研究下 lower_bound 和 upper_bound 的实现。


先看普通的二分查找

int binSearch(int* array ,int x,int head,int tail){ //循环版本  
	while(head<=tail){  
		int mid=(head+tail)/2;  
		if(List[mid]==x)  
			return mid;  
		else if(List[mid]>x){ //注意别写反  
			tail=mid-1;  
		}  
		else{  
			head=mid+1;  
		}  
	}  
	return -1;  
}  

lower_bound 返回大于等于给定key值的位置。

不断二分,右边界(last)找到大于等于key值的最左边的位置,用左边界(first)不断向右边界逼近。


int mylower_bound(int* array ,int size,int key){
	int first = 0, middle ,last = size-1;
	while(first<last){
		middle = (first+last) >> 1;
		if(array[middle] <key ) //当middle小于要找的位置 , first +1 也不会超过key的位置,最多相同
			 first = middle + 1;
 		else
			last = middle ; //middle有可能等于要找的位置 , last = middle , 用first不断逼近
		
	}
	return first;
}


upper_bound 返回大于给定key值的位置。

注意与lower_bound的不同。不断二分,右边界(last)找到最靠左的比key值大的位置,用左边界(first)不断向右边界逼近。


int myupper_bound(int* array ,int size,int key){
	int first = 0, middle ,last = size-1;
	while(first<last){
		middle = (first+last) >> 1;
		if(array[middle] >key ) //此时的middle一定大于要找的位置。用first不断逼近
			last = middle ;
		else
			first = middle +1; //当middle等于要找的位置, 我们记录first = middle+1
		
	}
	return first;
}


STL 源码

这个算法中,first是最终要返回的位置
int lower_bound(int *array, int size, int key)
{
    int first = 0, middle;
    int half, len;
    len = size;

    while(len > 0) {
        half = len >> 1;
        middle = first + half;
        if(array[middle] < key) {     
            first = middle + 1;          
            len = len-half-1;       //在右边子序列中查找
        }
        else
            len = half;            //在左边子序列(包含middle)中查找
    }
    return first;
}
int upper_bound(int *array, int size, int key)
{
    int first = 0, len = size-1;
    int half, middle;

    while(len > 0){
        half = len >> 1;
        middle = first + half;
        if(array[middle] > key)     //中位数大于key,在包含last的左半边序列中查找。
            len = half;
        else{
            first = middle + 1;    //中位数小于等于key,在右半边序列中查找。
            len = len - half - 1;
        }
    }
    return first;
}



posted @ 2015-09-10 17:30  编程菌  阅读(277)  评论(0编辑  收藏  举报