-
概述
- 在 C++ 中,
std::sort
是一个非常有用的算法函数,它用于对给定范围内的元素进行排序。这个函数定义在<algorithm>
头文件中。
- 在 C++ 中,
-
函数原型
template< class RandomIt > void sort( RandomIt first, RandomIt last );
template< class RandomIt, class Compare > void sort( RandomIt first, RandomIt last, Compare comp );
- 其中
first
和last
是迭代器,它们定义了要排序的元素范围(左闭右开区间,即[first, last)
)。RandomIt
是一个随机访问迭代器类型,它可以是指针(比如指向数组元素的指针)或者是符合随机访问迭代器要求的容器迭代器(如std::vector
、std::array
等容器的迭代器)。第二个重载函数中的comp
是一个比较函数,用于自定义元素的比较规则。
-
使用示例(默认升序排序)
- 下面是一个对
std::vector
中的整数进行排序的例子:#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> numbers = {5, 2, 8, 1, 9}; std::sort(numbers.begin(), numbers.end()); for (int num : numbers) { std::cout << num << " "; } return 0; }
在这个例子中,
numbers.begin()
和numbers.end()
定义了要排序的范围,也就是整个numbers
向量。std::sort
函数会按照升序对向量中的元素进行排序。输出结果将是1 2 5 8 9
。 -
自定义比较函数(降序排序)
- 如果想要按照降序对元素进行排序,可以提供一个自定义的比较函数。例如:
#include <iostream> #include <vector> #include <algorithm> bool compare(int a, int b) { return a > b; } int main() { std::vector<int> numbers = {5, 2, 8, 1, 9}; std::sort(numbers.begin(), numbers.end(), compare); for (int num : numbers) { std::cout << num << " "; } return 0; }
这里定义了一个
compare
函数,它接受两个整数a
和b
,当a > b
时返回true
。将这个函数作为std::sort
的第三个参数传递进去,就可以让std::sort
按照降序对numbers
向量中的元素进行排序。输出结果将是9 8 5 2 1
。
- 下面是一个对
-
时间复杂度
std::sort
通常实现为一种混合排序算法,例如 Introsort(内省排序)。它的平均时间复杂度是,其中n
是要排序的元素数量。在最坏情况下,时间复杂度也是,这比一些简单的排序算法(如冒泡排序在最坏情况下的)要高效得多。
-
稳定性
std::sort
是不稳定的排序算法。所谓不稳定,是指在排序过程中,相等元素的相对顺序可能会改变。例如,有一个包含(1, 'a')
和(1, 'b')
的数组(这里假设第一个元素是整数,用于排序,第二个元素是字符用于区分),经过std::sort
排序后,不能保证(1, 'a')
和(1, 'b')
的相对顺序不变。如果需要稳定排序,可以考虑使用std::stable_sort
,它的时间复杂度在平均和最坏情况下也是,但它保证相等元素的相对顺序不变。
sort中使用 lambda
lambda 表达式简介
lambda 表达式是 C++ 11 引入的一种匿名函数机制,它的基本语法形式如下:
[capture list](parameter list) -> return type {
function body
}
capture list
(捕获列表):用于指定在 lambda 函数体中可以访问的外部变量。它可以为空,表示不捕获任何外部变量;也可以包含按值捕获(如[x]
,这里x
是外部变量,会将其值复制到 lambda 内部使用)或者按引用捕获(如[&y]
,y
是外部变量,在 lambda 内部通过引用访问它,对其修改会影响外部的变量值)等不同方式。parameter list
(参数列表):和普通函数的参数列表类似,定义了 lambda 函数接受的参数。return type
(返回类型):可以显式指定返回类型,如果不指定,编译器会根据函数体中的返回语句自动推导返回类型(对于简单情况通常能正确推导)。function body
(函数体):包含了具体要执行的语句,实现相应的功能
使用 lambda 表达式结合std::sort
进行排序
示例一:对简单数组进行降序排序
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9};
// 使用lambda表达式自定义降序排序规则
std::sort(numbers.begin(), numbers.end(), [](int a, int b) {
return a > b;
});
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}
在上述代码中,std::sort
的第三个参数使用了一个 lambda 表达式。这个 lambda 表达式接受两个int
类型的参数a
和b
,并返回a > b
的结果,意味着按照降序对numbers
向量中的元素进行排序。
示例二:对包含结构体的数组根据结构体成员进行排序
假设有如下结构体表示学生信息:
struct Student {
std::string name;
int score;
};
现在要根据学生的成绩对学生结构体数组进行排序,可以这样写:
#include <iostream>
#include <algorithm>
#include <vector>
struct Student {
std::string name;
int score;
};
int main() {
std::vector<Student> students = {
{"Alice", 80},
{"Bob", 90},
{"Charlie", 70}
};
// 使用lambda表达式按照学生成绩升序排序
std::sort(students.begin(), students.end(), [](const Student& s1, const Student& s2) {
return s1.score < s2.score;
});
for (const Student& s : students) {
std::cout << s.name << " " << s.score << std::endl;
}
return 0;
}
示例三:使用捕获列表的情况
假设我们有一个外部变量,想要在排序的 lambda 表达式中使用它来影响排序规则,比如根据一个外部给定的阈值来筛选元素进行排序:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9};
int threshold = 5;
// 使用lambda表达式结合捕获外部变量,对大于阈值的元素升序排序
std::sort(numbers.begin(), numbers.end(), [threshold](int a, int b) {
// 只比较大于阈值的元素
if (a > threshold && b > threshold) {
return a < b;
}
return false;
});
for (int num : numbers) {
std::cout << num << " ";
}
return 0;
}
在这个例子中,lambda
表达式的捕获列表[threshold]
按值捕获了外部变量threshold
,然后在 lambda 函数体中根据这个阈值来决定元素的比较和排序逻辑,这里只对大于阈值的元素进行升序排序的比较,其他情况返回false
(表示不交换顺序)。
总之,通过使用 lambda 表达式与std::sort
结合,可以方便快捷地根据各种复杂或简单的自定义规则来对容器中的元素进行排序,增强了排序操作的灵活性。
std::sort的示例代码
以下是一些不同场景下使用 std::sort
的示例代码,涵盖了对基本数据类型数组、结构体数组以及自定义比较规则等情况的排序操作:
示例一:对整数数组进行升序排序
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
std::vector<int> numbers = {5, 2, 8, 1, 9};
std::sort(numbers.begin(), numbers.end());
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个示例中,使用 std::sort
对 std::vector
容器中的整数元素按照默认的升序规则进行排序,然后通过循环输出排序后的数组元素,输出结果为 1 2 5 8 9
。
示例二:对字符数组进行降序排序(使用自定义比较函数)
#include <iostream>
#include <algorithm>
#include <cstring>
// 自定义比较函数,用于实现字符的降序比较
bool compareChars(char a, char b) {
return a > b;
}
int main() {
char characters[] = "hello";
int size = std::strlen(characters);
std::sort(characters, characters + size, compareChars);
std::cout << characters << std::endl;
return 0;
}
这里定义了 compareChars
函数来指定字符的降序比较规则,然后使用 std::sort
对字符数组 characters
进行排序,最终输出排序后的字符数组,结果为 "olleh"
。
示例三:对结构体数组根据结构体成员进行排序
#include <iostream>
#include <algorithm>
#include <vector>
// 定义结构体表示学生信息
struct Student {
std::string name;
int score;
};
// 自定义比较函数,按照学生成绩升序排序
bool compareStudents(const Student& s1, const Student& s2) {
return s1.score < s2.score;
}
int main() {
std::vector<Student> students = {
{"Alice", 80},
{"Bob", 90},
{"Charlie", 70}
};
std::sort(students.begin(), students.end(), compareStudents);
for (const Student& s : students) {
std::cout << s.name << " " << s.score << std::endl;
}
return 0;
}
此示例定义了 Student
结构体来表示学生信息,包含姓名和成绩两个成员。通过自定义 compareStudents
函数,按照学生成绩的升序规则,使用 std::sort
对 students
结构体数组进行排序,之后循环输出排序后的学生信息,输出顺序会按照成绩从小到大排列。
示例四:使用函数对象(仿函数)实现复杂比较规则的排序
#include <iostream>
#include <algorithm>
#include <vector>
// 定义结构体表示商品信息
struct Product {
std::string name;
int quantity;
double price;
};
// 定义函数对象(仿函数),按照商品库存数量降序排序,如果库存相同则按照价格升序排序
class ProductComparator {
public:
bool operator()(const Product& p1, const Product& p2) const {
if (p1.quantity!= p2.quantity) {
return p1.quantity > p2.quantity;
}
return p1.price < p2.price;
}
};
int main() {
std::vector<Product> products = {
{"Apple", 10, 5.5},
{"Banana", 8, 3.2},
{"Orange", 10, 4.0}
};
std::sort(products.begin(), products.end(), ProductComparator());
for (const Product& p : products) {
std::cout << p.name << " " << p.quantity << " " << p.price << std::endl;
}
return 0;
}
在这个示例中,针对 Product
结构体表示的商品信息,定义了 ProductComparator
函数对象,其重载的 operator()
函数实现了复杂的比较规则:先按照商品库存数量降序排序,如果库存数量相同,则按照价格升序排序。使用 std::sort
结合这个函数对象对 products
向量中的商品结构体进行排序,最后输出排序后的商品信息。
这些示例展示了 std::sort
在不同场景下的应用,你可以根据实际需求灵活运用该函数来实现各种排序操作。