1. 程式人生 > >二分查詢演算法的幾種實現

二分查詢演算法的幾種實現

最簡單的二分

1.迴圈實現


template <typename T>
int binary_search(const vector<T> &set, const T &value)
{
	auto low = set.begin();
	auto high = set.end();
	auto high_dump = high;
	auto low_dump = low;

	auto mid = low + ((high - low) >> 1);
    /*1. mid=(low+high)/2,如果 low 和 high 太大就會產生溢位*/
	while ((low <= high) && (mid != high_dump))   /*2. 一定是 <= */
	{
		if (*mid == value)
			return mid - low_dump;
	      /*3. 一定要+1,-1,不然當 low = high時,就會產生死迴圈*/
		if (*mid < value)
			low = mid + 1;
		else
			high = mid - 1;
		mid = low + ((high - low) >> 1);
	}
	return -1;
}

2. 遞迴實現

template <typename ForwardIt, class T>
bool binary_search(ForwardIt frist, ForwardIt last, const T &value)
{
	if (frist > last)
		return false;
	auto mid = frist + ((last - frist) >> 1);
	if (*mid == value)
		return true;
	if (*mid < value)
		binary_search(mid + 1, last, value);
	else
		binary_search(frist, mid - 1, value);
}

幾種變式

1.查詢第一個值等於給定值的元素

/*  1.查詢第一個值等於給定值的元素
[1,3,4,5,6,8,8,8,11,18]
找到返回下標,找不到返回 -1 */

template <typename ForwardIt, class T>
int binary_search(ForwardIt low, ForwardIt high, const T &value)
{
	auto low_dump = low;
	auto high_dump = high ;
	auto mid = low + ((high - low) >> 1);
	while  ((low <= high) && (mid != high_dump))
	{
		if (*mid < value)
			low = mid + 1;
		else if (*mid > value)
			high = mid - 1;
		else
		{
			if ((mid == low_dump) || (*(mid - 1) != value))
				return mid - low_dump;
			else
				high = mid - 1;  /*縮排high的距離*/
		}
		mid = low + ((high - low) >> 1);
	}
	return -1;
}

2.查詢最後一個值等於給定值的元素

同上

3. 查詢第一個大於等於給定值的元素

/*3.查詢第一個大於等於給定值的元素
[1,3,4,5,6,8,8,8,11,18]
找到返回下標,找不到返回 -1
*/
template <typename ForwardIt, class T>
int binary_search(ForwardIt low, ForwardIt high, const T &value)
{
	auto low_dump = low;
	auto high_dump = high;
	auto mid = low + ((high - low) >> 1);
	while ((low <= high) && (mid != high_dump))
	{
		if (*mid < value)
			low = mid + 1;
		else if (*mid >= value)
		{
			if ((mid == low_dump) || (*(mid - 1) < value))
				return mid - low_dump;
			else
				high = mid - 1;
		}
		mid = low + ((high - low) >> 1);
	}
	return -1;
}

4. 查詢最後一個小於等於給定值的元素

/*4. 查詢最後一個小於等於給定值的元素
[1,3,4,5,6,8,8,8,11,18]
找到返回下標,找不到返回 -1
*/
template <typename ForwardIt, class T>
int binary_search(ForwardIt low, ForwardIt high, const T &value)
{
	auto low_dump = low;
	auto high_dump = high;
	auto mid = low + ((high - low) >> 1);
	while ((low <= high) && (mid != high_dump))
	{
		if (*mid <= value)
		{
			if ((mid == high_dump - 1) || (*(mid + 1) > value))
				return mid - low_dump;
			else
				low = mid + 1;
		}
		else if (*mid > value)
			high = mid - 1;
		mid = low + ((high - low) >> 1);
	}
	return -1;
}