二分查找自用模板

二分查找算法用于在一个有序的列表中查找某个值的位置,列表一般是升序排列的。循环比较中间值A[mid]和需要查找的值x,如果x小于等于中间值,那么在左边找;如果x大于中间值,那么去右边找。
二分查找的思想很简单,但是有很多种写法,我自己用的模板是仿照STL的二分函数,即有两个版本,一个是查找第一个大于等于x的值的下标,若找不到则返回尾后指针;另一个版本是查找第一个大于x的值的下标,找不到返回尾后指针。

我的自用二分模板

#include <bits/stdc++.h>
using namespace std;

// 找出第一个大于等于x的元素的下标
int search_lower_bound(int *A, int left, int len, int x) {
	int mid, right = left + len;
	while (left < right) {
		mid = (left + right) / 2;
		if (x <= A[mid])
			right = mid;
		else
			left = mid + 1;
	}
	return left;
}

// 找出第一个大于x的元素的下标
int search_upper_bound(int *A, int left, int len, int x) {
	int mid, right = left + len;
	while (left < right) {
		mid = (left + right) / 2;
		if (x < A[mid])
			right = mid;
		else
			left = mid + 1;
	}
	return left;
}
const int LEN = 8;
int A[LEN] = { 1, 1, 4, 5, 14, 19, 19, 810 }; //升序数组
int main() {
	for (int i = 0; i < LEN; i++) cout << A[i] << " "; cout << endl;
	int x;
	while (cin >> x) {
		int lo = search_lower_bound(A, 0, LEN, x);
		int up = search_upper_bound(A, 0, LEN, x);
		printf("A[%d] >= %d\n", lo, x);
		printf("A[%d] > %d\n", up, x);
	}
	return 0;
}

两个函数的唯一区别就是 if (x < A[mid]),如果带等于号,则返回第一个大于等于x的值的下标;若不带等于号,则返回第一个大于x的值的下标。

STL 二分函数
STL 二分查找函数更加灵活,它是模板函数,支持多种类型,包括自定义类型(需重载小于运算符),可以传lambda表达式自定义比较规则。
下面附上两个demo演示 STL 二分函数如何应用在自定义类型数组以及降序的整型数组。

降序数组demo

#include <bits/stdc++.h>
using namespace std;
int main() {
	int A[] = {10,8,6,4,2}; // 降序数组
	size_t x1 = lower_bound(A, A+5, 3, [](int a, int b) { return a > b; }) - A;
	size_t x2 = upper_bound(A, A+5, 3, [](int a, int b) { return a > b; }) - A;
	size_t x3 = lower_bound(A, A+5, 4, [](int a, int b) { return a > b; }) - A;
	size_t x4 = upper_bound(A, A+5, 4, [](int a, int b) { return a > b; }) - A;
	cout << x1 << endl; // 第一个小于等于3的元素下标
	cout << x2 << endl; // 第一个小于3的元素下标
	cout << x3 << endl; // 第一个小于等于4的元素下标
	cout << x4 << endl; // 第一个小于4的元素下标

	return 0;
}

自定义类型demo

#include <bits/stdc++.h>
using namespace std;
struct MyPair {
	int a,b;
	MyPair(int _a, int _b) : a(_a), b(_b) {}
	bool operator<(const MyPair &other) {
		if (a != other.a)	return a < other.a;
		return b < other.b;
	}
};
int main() {
	vector<MyPair> v{{1,2}, {3,4}, {5,6}};
	int x = lower_bound(v.begin(), v.end(), MyPair(3,4)) - v.begin();
	cout << x << endl;
	return 0;
}
发布了105 篇原创文章 · 获赞 24 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/Kwansy/article/details/103598323
今日推荐