Функция std::sort() из заголовочного файла <algorithm>
предназначена для сортировки диапазон элементов.
Первые два параметра функции представляют начальный и конечный итераторы сортируемого диапазона. Третий необязательный параметр представляет функцию сравнения или компаратор.
Если компаратор не указан, то элементы сортируются по возрастанию (например, строки сортируются в лексикографическом порядке).
Например, отсортируем вектор строк по умолчанию:
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<std::string> people {"Tom", "Bob", "Sam", "Alice", "Kate"}; std::sort(begin(people), end(people)); // сортируем вектор people for(const auto& person: people ) { std::cout << person << std::endl; } }
В данном случае сортируем весь вектор people, поэтому в функцию std::sort передаются итераторы на начало и конец вектора. И в данном случае мы получим следующий результат:
Alice Bob Kate Sam Tom
То есть строки сортируются в лексикографическом порядке (как идут в алфавите начальные буквы строк). Теперь применим компаратор, например, отсортируем вектор в зависимости от длины строк:
#include <iostream> #include <vector> #include <algorithm> bool compare(const std::string& left, const std::string& right) { return left.length() < right.length(); } int main() { std::vector<std::string> people {"Tom", "Bob", "Sam", "Alice", "Kate"}; std::sort(begin(people), end(people), compare); for(const auto& person: people ) { std::cout << person << std::endl; } }
В качестве компаратора здесь определена функция compare. Компаратор должен принимать два значения и возвращать значение типа bool - если первое значение должно идти до второго,
то возвращается true
. И в случае выше функция compare принимает две строки и возвращает true
, если длина первой строки меньше второй. Соответственно теперь консольный
вывод будет следующим:
Tom Bob Sam Kate Alice
То есть строки отсортированы по длине по возрастанию.
Начиная со стандарта C++20 также для сортировки элементов контейнера можно использовать упрощенный подход - функцию std::ranges::sort(), которая в качестве параметра принимает сортируемый контейнер:
#include <iostream> #include <vector> #include <algorithm> #include <ranges> // для std::ranges int main() { std::vector<std::string> people {"Tom", "Bob", "Sam", "Alice", "Kate"}; std::ranges::sort(people); // сортируем вектор people for(const auto& person: people ) { std::cout << person << std::endl; } }
По умолчанию данные сортируются по возрастанию (в случае со строками в лексикографическом порядке)
Alice Bob Kate Sam Tom
Также в качестве второго параметра можно передать функцию компаратора, которая определяет принцип сравнения значений:
#include <iostream> #include <vector> #include <algorithm> #include <ranges> // для std::ranges bool compare(const std::string& left, const std::string& right) { return left.length() < right.length(); } int main() { std::vector<std::string> people {"Tom", "Bob", "Sam", "Alice", "Kate"}; std::ranges::sort(people, compare); // сортируем вектор people с помощью компаратора compare for(const auto& person: people) { std::cout << person << std::endl; } }
С помощью функции-компаратора compare упорядочиваем элементы по возрастанию их длин:
Tom Bob Sam Kate Alice
Функция std::ranges::sort
поддерживает проекцию данных для функции компаратора. Например:
#include <iostream> #include <vector> #include <algorithm> #include <ranges> class Person { public: Person(std::string name): name{name}{} std::string getName() const {return name;} private: std::string name; }; bool compare(const std::string& left, const std::string& right) { return left.length() < right.length(); } std::string personToString(const Person& person){ return person.getName();} int main() { std::vector<Person> people {Person{"Tom"}, Person{"Kate"}, Person{"Bob"}, Person{"Alice"}}; std::ranges::sort(people, compare, personToString); for(const auto& person: people ) { std::cout << person.getName() << std::endl; } }
Здесь сортируемый вектор содержит объекты Person, который хранит имя в строковом поле name. Мы могли бы определить для сравнения данных Person еще одну функцию компаратора.
Но в данном случае мы также можем использовать и ранее определенную функцию компаратора для сравнения строк. Но в этом случае в std::ranges::sort()
в качестве
третьего параметра передается функция проекции из Person в std::string - функция personToString, которая возвращает имя объекта Person. Именно эти данные и будут передаваться в
функцию компаратора при сравнении двух объектов.