1,sort—函数
默认使用小于号进行排序,如果想自定义比较规则,可以传入第三个参数,一个普通的函数、一个Lambda函数或者一个函数对象均可。
1. 使用普通函数作为比较函数:
#include <algorithm>
#include <iostream>
#include <vector>
bool compare(int a, int b) {
// 自定义比较规则,例如按照数字的绝对值升序排序
return abs(a) < abs(b);
}
int main() {
std::vector<int> myVector = {-3, 1, -4, 1, 5, -9, 2, -6, 5, 3, 5};
std::sort(myVector.begin(), myVector.end(), compare);
// 输出排序后的结果
for (int num : myVector) {
std::cout << num << " ";
}
return 0;
}
代码分析:
这个比较函数的作用是根据两个整数的绝对值大小来进行升序排序。让我们解释一下函数体中的内容:
-
abs(a)
: 这是C++标准库中的函数,用于返回一个整数的绝对值。 -
abs(b)
: 同样,这是对整数b
求绝对值。 -
return abs(a) < abs(b);
: 这一行代码使用了关系运算符<
来比较两个整数的绝对值大小。如果abs(a)
的绝对值小于abs(b)
,则返回true
,表示a
应该排在b
的前面;如果不成立,返回false
,表示b
应该排在a
的前面。
这种比较规则会导致整数按照它们的绝对值升序排序。例如,如果原始序列是 {-3, 1, -4, 1, 5, -9, 2, -6, 5, 3, 5}
,排序后的结果将是 1, 1, 2, 3, -3, -4, 5, -5, 5, -6, -9
。
2. 使用Lambda函数作为比较函数:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> myVector = {-3, 1, -4, 1, 5, -9, 2, -6, 5, 3, 5};
std::sort(myVector.begin(), myVector.end(), [](int a, int b) {
// 自定义比较规则,例如按照数字的绝对值降序排序
return abs(a) > abs(b);
});
// 输出排序后的结果
for (int num : myVector) {
std::cout << num << " ";
}
return 0;
}
代码分析:
让我们解释一下 Lambda 表达式的不同部分:
std::sort(myVector.begin(), myVector.end(), [](int a, int b) {
// 自定义比较规则,例如按照数字的绝对值降序排序
return abs(a) > abs(b);
});
-
[](int a, int b)
: 这是 Lambda 表达式的头部,其中[]
表示捕获列表(capture list)。在这里,[]
表示不捕获任何外部变量。int a, int b
是参数列表,表示这个 Lambda 表达式接受两个整数参数。 -
{}
: 这是 Lambda 表达式的主体,包含了实际的代码块。在这里,Lambda 表达式定义了一个比较规则,按照数字的绝对值降序排序。 -
return abs(a) > abs(b);
: 这是 Lambda 表达式的返回语句。它比较a
和b
的绝对值,如果abs(a)
的绝对值大于abs(b)
,则返回true
,表示a
应该排在b
的前面,实现了降序排序的规则。
整个 Lambda 表达式的作用是为 std::sort
函数提供一个自定义的比较规则,用于对 myVector
中的元素进行排序。在这个例子中,元素按照它们的绝对值降序排序。
题目描述
给定一个长度为 N 的数组 A,请你先从小到大输出它的每个元素,再从大到小输出它的每个元素。
输入描述
第一行包含一个整数 N。
第二行包含 N 个整数 1,...,a1,...,an,表示数组 A 的元素。
1N≤100000,−1000000000≤ai≤1000000000。
输出描述
输出共两行,每行包含 N 个整数,表示答案。
输入输出样例
输入
5 1 3 2 6 5
输出
1 2 3 5 6 6 5 3 2 1
#include <bits/stdc++.h>
using namespace std;
const int N = 500000;
int main() {
int a[N];
int n;
cin>>n;
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a, a + n);
// 输出排序后的数组
for (int i = 0; i < n; i++)
cout << a[i] << ' ';
cout << '\n';
// 降序排序
sort(a, a + n, greater<int>());
// 输出降序排序后的数组
for (int i = 0; i < n; i++)
cout << a[i] << ' ';
cout << '\n';
return 0;
}
代码分析:
这段代码中,N
是数组 a
的最大大小,而 n
是实际数组的大小。你可以将 N
当成数组的容量,而 n
表示当前实际存储的元素个数。
最值查找
min_element
函数:
返回容器中的最小元素的迭代器(指向最小元素的位置)。
max_element
函数:
返回容器中的最大元素的迭代器(指向最大元素的位置)。
nth_element函数:
是一个C++标准库中的函数,用于对容器进行部分排序,将指定位置的元素放到正确的位置上。
#include <algorithm>
// 用法:
nth_element(startIterator, nthIterator, endIterator);
// 参数:
// startIterator: 范围的起始迭代器
// nthIterator: 被放置到正确位置的元素的迭代器
// endIterator: 范围的结束迭代器
nth_element 函数通过部分排序的方式,将 nthIterator 指向的元素放置到容器中正确的位置上。
在 [startIterator, nthIterator) 范围内的元素都不大于 *nthIterator。
在 (nthIterator, endIterator] 范围内的元素都不小于 *nthIterator。
nthIterator 所指向的元素现在在容器中的 "nth" 位置上。这并不是对整个范围的排序,
例子:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
// 将第5个元素放在正确的位置上
auto nthIterator = numbers.begin() + 4; // 指定位置为第5个元素
nth_element(numbers.begin(), nthIterator, numbers.end());
// 输出部分排序后的结果
for (int num : numbers) {
std::cout << num << ' ';
}
std::cout << '\n';
return 0;
}
代码分析:
在这个例子中,nth_element
将第5个元素放置到正确的位置上,使得它之前的元素都不大于它,之后的元素都不小于它。最终输出的部分排序后的容器内容为 3 1 2 1 3 5 4 6 5 9 5
。
例题:
成绩分析
题目描述
小蓝给学生们组织了一场考试,卷面总分为 100 分,每个学生的得分都是一个 0 到 100 的整数。
请计算这次考试的最高分、最低分和平均分。
输入描述
输入的第一行包含一个整数 n (1≤n≤10000),表示考试人数。
接下来 n 行,每行包含一个 0 至 100 的整数,表示一个学生的得分。
输出描述
输出三行。
第一行包含一个整数,表示最高分。
第二行包含一个整数,表示最低分。
第三行包含一个实数,四舍五入保留正好两位小数,表示平均分。
输入输出样例
#include <bits/stdc++.h>
using namespace std;
const int N=10000;
int main()
{
int a[N];
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>a[i];
cout<<*max_element(a,a+n)<<'\n';
cout<<*min_element(a,a+n)<<'\n';
int sum=0;
for(int i=0;i<n;i++)
sum+=a[i];
cout<<fixed<<setprecision(2)<<sum*1.0/n<<'\n';
return 0;
}
代码分析:
-
fixed
: 这是一个iomanip
头文件中定义的标记。将它设置为fixed
表示以固定的小数位数输出浮点数。如果不设置fixed
,则默认是以科学计数法输出。 -
setprecision(2)
: 这是另一个iomanip
头文件中的函数,用于设置输出的浮点数精度。在这里,设置为2
表示输出的浮点数保留两位小数。 -
sum * 1.0 / n
: 这是计算平均值的表达式。将sum
乘以1.0
的目的是将其中一个操作数(sum
或n
)转换为浮点数,以确保在除法时得到的结果是浮点数而不是整数。这样可以保留小数部分,得到更精确的平均值。 -
'\n'
: 最后是换行符,用于将输出移到下一行。
所以,整个语句的作用是以固定的小数位数(两位小数)输出一组数字的平均值。
二分查找
库函数只能对数组进行二分查找,并且这个数组中的元素是单调的
lower_bound
函数:
返回一个迭代器,指向在有序范围 [startIterator, endIterator) 中第一个不小于 value 的元素位置。
upper_bound
函数:
返回一个迭代器,指向在有序范围 [startIterator, endIterator) 中第一个大于 value 的元素位置。
如果不存在返回最后一个元素的下一个位置。
例题
二分查找数组元素
题目描述
给定一个数组,其采用如下代码定义:
int data[200];
for(i = 0 ; i < 200 ; i ++)data[i] = 4 * i + 6;
先给定某个数(在 data 数组中),请你求出它在数组中的位置。
输入描述
输入一个待查找的整数(该整数一定在数组data中)。
输出描述
输出该整数在数组中的指标
#include <bits/stdc++.h>
using namespace std;
int main() {
int data[200];
for (int i = 0; i < 200; i++) {
data[i] = 4 * i + 6;
}
int x;
cin >> x;
cout <<(lower_bound(data,data+200,x) - data)<<'\n';
return 0;
}
lower_bound(data, data + 200, x)
: 这部分使用了 lower_bound
函数,它在有序范围内查找第一个不小于 x
的元素的位置。如果找到了这样的元素,它返回指向该元素的迭代器;如果没有找到,它返回指向超过 x
的最小元素的迭代器,即数组中的某个位置。
解法2:
大小写转换
islower/isupper函数
islower(int c)
: 用于检查字符c
是否为小写字母。如果c
是小写字母,则函数返回非零值(true),否则返回零(false)。isupper(int c)
: 用于检查字符c
是否为大写字母。如果c
是大写字母,则函数返回非零值,否则返回零。
tolower 和 toupper 函数:
tolower(int c)
: 将大写字母c
转换为相应的小写字母;如果c
不是大写字母,则返回c
本身。toupper(int c)
: 将小写字母c
转换为相应的大写字母;如果c
不是小写字母,则返回c
本身。- 全排列
- prev_permutation()函数
prev_permutation
是 C++ 标准库 <algorithm>
头文件中提供的一个函数,用于生成给定范围内的前一个排列(字典序上的前一个排列)。这个函数通常与 next_permutation
配套使用,用于在一个排列序列中进行遍历。
- first, last: 定义了要修改排列的范围,表示
[first, last)
区间。
函数的作用是将 [first, last)
区间内的元素重新排列为其字典序的前一个排列。如果成功生成了前一个排列,则返回 true
,否则返回 false
。
next_permutation函数
是 C++ 标准库 <algorithm>
头文件中提供的一个函数,用于生成给定范围内的下一个排列(字典序上的下一个排列)。这个函数通常与 prev_permutation
配套使用,用于在一个排列序列中进行遍历。
函数的作用是将 [first, last)
区间内的元素重新排列为其字典序的下一个排列。如果成功生成了下一个排列,则返回 true
,否则返回 false
需要注意的是,next_permutation
在修改排列时会直接修改原始序列,所以如果需要保留原始序列,最好在调用之前对序列进行备份。此外,排列的开始状态应当是按字典序递增的,否则 next_permutation
可能无法正常工作。
其他库函数·
memset()函数
memset
是 C/C++ 中的一个函数,用于将一块内存区域的内容设置为指定的值。它通常用于初始化数组或清空数据结构的内存。
void* memset(void* ptr, int value, size_t num);
- ptr: 要设置值的内存的起始地址。
- value: 要设置的值,通常是一个无符号字符(unsigned char)。
- num: 要设置的字节数。
char buffer[10];- // 使用memset将buffer数组的内容设置为0
- memset(buffer, 0, sizeof(buffer));
- 对于非字符类型的数组可能会产生未定义行为
- swap()函数—交换函数,交换两个函数的值。
- reverse()函数
reverse
是 C++ 标准库中<algorithm>
头文件中提供的一个函数,用于反转(颠倒顺序)指定范围内的元素序列。- first, last: 定义了要反转的范围,表示
[first, last)
区间。 -
reverse
函数会将范围[first, last)
内的元素顺序颠倒,即原来在前的元素移到最后,原来在后的元素移到最前。可以用于颠倒字符串、数组等容器类型中的元素顺序。 -
eg:vector<int> vec={1,2,3,4,5};
-
reverse(vec.begin(),vec.end());
-
unique函数
-
是 C++ 标准库中
<algorithm>
头文件中提供的一个函数,用于在指定范围内去除相邻的重复元素,从而保留唯一元素。 - first, last: 定义了要去除重复元素的范围,表示
[first, last)
区间。 -
unique
函数会将范围[first, last)
中相邻的重复元素只保留一个,也就是带一个出现的元素,并返回一个新的“尾后”迭代器,指向去重后的范围的末尾。去重后的范围并没有真正缩短,而是将重复的元素移到范围的末尾,返回的迭代器指向这个新的尾后位置。 -
first:指向容器中要去重的第一个元素的迭代器。
last:指向容器中要去重的最后一个元素的下一个迭代器
使用unique函数需要先排序