您的位置:首页 > 其它

二分查找及其变形总结

2015-09-16 16:25 423 查看
题目:在一个已经排好序的数组中,查找关于key相关条件的下标。
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

//0. 查找是否存在某个元素。说明:low是第一个元素下标;high是最后一个元素的下标
int originBinarySearch(int *arr, int low, int high, int key)
{
    assert(arr!=NULL && low >= 0 && high - low >= 0);
    int mid = 0;
    while(low <= high){
        mid = (low + high) / 2;
        if(arr[mid] == key){    //由于需要找和key相等的值,自然首先判断是否相同
            return mid;
        }else if(arr[mid] < key){   //如果不相等,分两种情况:(1)小于key
            low = mid + 1;
        }else {     //(2)大于key
            high = mid - 1;
        }
    }
    return -1;
}

//1. 查找第一次出现的位置(元素可能有重复)
//注意返回left:如果找到就是第一次出现的位置;如果没找到就是第一个大于key的数
//(总结:返回的是不小于(>=,大于等于)key的最靠前数的下标)
int bSearchFirstIndex(int* arr, int low, int high, int key)
{
    assert(arr != NULL && low >= 0 && high - low >= 0);
	int mid, left = low, right = high;
	while(left <= right)
	{
		mid = (left + right) >> 1;
		if(arr[mid] >= key) right = mid - 1;    //如果要求是返回大于key的第一个数的位置则将arr[mid] >= key修改为arr[mid] > key
		else left = mid + 1;
	}
	return left;
}

//要求返回大于key的第一个数的位置
int bSearchBigerIndex(int* arr, int low, int high, int key)
{
    assert(arr != NULL && low >= 0 && high - low >= 0);
	int mid, left = low, right = high;
	while(left <= right)
	{
	    printf("low:<%d>\tmid:<%d>\thigh:<%d>\n", low, mid, high);
		mid = (left + right) >> 1;
		if(arr[mid] > key) right = mid - 1;
		else left = mid + 1;
	}
	return left;
}

//2. 查找最后一次出现的位置(元素可能有重复)
//注意返回right:如果找到就是第一次出现的位置;如果没找到就是第一个大于key的数
//(总结:返回的是不大于(<=,小于等于)key的最靠后数的下标)
int bSearchLastIndex(int* arr, int low, int high, int key)
{
    assert(arr != NULL && low >= 0 && high - low >= 0);
	int mid, left = low, right = high;
	while(left <= right)
	{
		mid = (left + right) >> 1;
		if(arr[mid] > key) right = mid - 1;     //如果要求是返回小于key的第一个数的位置则将arr[mid] > key修改为arr[mid] >= key
		else left = mid + 1;
	}
	return right;
}

////要求返回小于key的第一个数的位置
int bSearchSmallerIndex(int* arr, int low, int high, int key)
{
    assert(arr != NULL && low >= 0 && high - low >= 0);
	int mid, left = low, right = high;
	while(left <= right)
	{
		mid = (left + right) >> 1;
		if(arr[mid] >= key) right = mid - 1;
		else left = mid + 1;
	}
	return right;
}
//变形:在循环有序数组中查找指定元素。
int findInCircle( int * arr, int low , int high, int key)
{
    int mid = 0;
    while(low<=high)
    {
        mid = low + (high - low) / 2;
        if (arr[mid] == key ) return mid;
        if(arr[mid]>=arr[low])	//前一部分为严格递增,后一部分为更小的循环递增数组
        {
            if(arr[low] <= key && key < arr[mid]) high = mid -1;
            else low = mid +1;
        }
        else	//后一部分为严格递增,前一部分为更小的循环递增数组
        {
            if(arr[mid] < key && key <= arr[high]) low = mid + 1;
            else high = mid -1;
        }
    }
    return -1;
}

本文参考了以下博客(向前辈学习,万分感谢!):

int63Ago博客:http://blog.csdn.net/int64ago/article/details/7425727

hackbuteer1博客:/article/1422718.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: