时间复杂度
二分查找的最优时间复杂度为 O(1)。
二分查找的平均时间复杂度和最坏时间复杂度均为O(logn) 。因为在二分搜索过程中,算法每次都把查询的区间减半,所以对于一个长度为n 的数组,至多会进行O(logn) 次查找。
空间复杂度
迭代版本的二分查找的空间复杂度为 O(1)。
递归(无尾调用消除)版本的二分查找的空间复杂度为O(logn).
代码
int binary_search(int start, int end, int key) { int ret = -1; // 未搜索到数据返回-1下标 int mid; while (start <= end) { mid = start + ((end - start) >> 1); // 直接平均可能会溢出,所以用这个算法 if (arr[mid] < key) start = mid + 1; else if (arr[mid] > key) end = mid - 1; else { // 最后检测相等是因为多数搜索情况不是大于就是小于 ret = mid; break; } } return ret; // 单一出口 }
qsort bsearch
qsort 函数有四个参数:数组名、元素个数、元素大小、比较规则。其中,比较规则通过指定比较函数来实现,指定不同的比较函数可以实现不同的排序规则。
比较函数的参数限定为两个 const void 类型的指针。返回值规定为正数、负数和 0。
比较函数的一种示例写法为:
1 2 3 4 5 6 7 8 9 10 11 | int compare(const void *p1, const void *p2) // int 类型数组的比较函数 { int *a = (int *)p1; int *b = (int *)p2; if (*a > *b) return 1; // 返回正数表示 a 大于 b else if (*a < *b) return -1; // 返回负数表示 a 小于 b else return 0; // 返回 0 表示 a 与 b 等价 } |
注意:返回值用两个元素相减代替正负数是一种典型的错误写法,因为这样可能会导致溢出错误。
cmp
bool cmp(int a,int b){
return a>b;//降序
}
bsearch--lower_bound
int A[100005]; // 示例全局数组 // 查找首个不小于待查元素的元素的地址 int lower(const void *p1, const void *p2) { int *a = (int *)p1; int *b = (int *)p2; if ((b == A || compare(a, b - 1) > 0) && compare(a, b) > 0) return 1; else if (b != A && compare(a, b - 1) <= 0) return -1; // 用到地址的减法,因此必须指定元素类型 else return 0; }
C++ 中的 lower_bound 和 upper_bound 函数
lower_bound()返回值是一个迭代器,返回指向大于等于key的第一个值的位置
对象:有序数组或容器
数组:
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
int a[]={1,2,3,4,5,7,8,9};
printf("%d",lower_bound(a,a+8,6)-a);
return 0;
}
输出:5