2 STL 常用函数
STL 中大量的函数在熟练掌握后可以提高写代码的效率。
使用 STL 中的函数需要包含头文件<algorithm>
。
sort 函数
std::sort
用于排序,会根据实际情况调整底层实现算法,时间复杂度 $O(n\log n)$,再也不用手写快排/归并。
该函数可以用于数组或vector
。使用数组时,传入需要排序区间的头指针和尾指针(左闭右开);使用vector
时传入迭代器。
| int arr[6] = {1,1,4,5,1,4};
std::sort(arr,arr + 6); // arr: [1,1,1,4,4,5]
std::vector<int> vec;
vec.push_back(1);
vec.push_back(9);
vec.push_back(8);
std::sort(vec.begin(),vec.end()); // vec: [1,8,9]
std::sort(vec.rbegin(),vec.rend()); // vec: [9,8,1]
|
std::sort
可以传入第三个参数。这个参数返回bool
值,是自定义的排序模式。该函数返回true
时,第一个参数所代表的元素应排在前面。
| // 大的排在前面,即降序排序
bool cmp(const int &a,const int &b){return a > b;};
std::sort(vec.begin(),vec.end(),cmp);
|
或者更简单地,直接使用匿名函数。
| // 依然是降序排序
std::sort(vec.begin(),vec.end(),[](const int &a,const int &b){return a > b;});
|
unique 函数
std::unique
用于去重,说的更明白些是将多个连续的相同元素变成一个。其时间复杂度应该是 $O(n)$。
该函数的调用方法和std::sort
类似,没有第三个参数。在实际执行时,会将指定范围内的数据进行去重,并返回去重后的尾地址(去重数组返回指针,去重vector
返回迭代器)。尾地址后的元素处于未指定状态。
| vector<int> a = {1,1,4,5,1,4};
int b = std::unique(a.begin(),a.end());
// a = [1,4,5,1,4,*], b = a.begin() + 5, * 代表处于未指定状态
|
如果要去掉所有重复的元素,做到真正的去重,可以先排序再使用该函数。
lower_bound 和 upper_bound 函数
两个函数都是在有序的数组或者vector
中寻找第一个满足某条件的元素。底层逻辑为二分查找,时间复杂度 $O(\log n)$。
std::lower_bound
:寻找第一个不小于某值的元素,并以指针或迭代器形式返回。
std::upper_bound
:寻找第一个大于某值的元素,并以指针或迭代器的形式返回。
具体来说可以举一个例子。
| std::vector<int> a = {1,4,5,7,3,9};
std::cout << std::lower_bound(a.begin(),a.end(),4) - a.begin() << std::endl; // 1,即这个元素为 a[1] = 4
std::cout << std::upper_bound(a.begin(),a.end(),5) - a.begin() << std::endl; // 3,即这个元素为 a[3] = 7
|
实际上这两个函数还可以传入第四个参数。实际上这个也不难掌握,上面的代码块也可以写作下面的四参数形式,输出结果是一样的。
| std::vector<int> a ={1,4,5,7,3,9};
auto cmp = [](const int &a,const int &b){return a < b;};
std::cout << std::lower_bound(a.begin(),a.end(),4,cmp) - a.begin() << std::endl;
std::cout << std::upper_bound(a.begin(),a.end(),5,cmp) - a.begin() << std::endl;
|
也就是说三参数的std::lower_bound
和std::upper_bound
实际上都等价于第四个参数是函数less<type>()
。实际运用时按照这个逻辑进行推演就好。
推演的例子
已知条件是,若传入auto cmp = [](const int &a,const int &b){return a < b;};
,那么std::lower_bound
寻找的是第一个不小于某值的函数。若我传入auto cmp = [](const int &a,const int &b){return a > b;};
,那么寻找的就是第一个不大于某值的函数(前提是序列要递减)。