Можно ли отсортировать std::list?

«Можно ли отсортировать std::list?» — вопрос из категории STL, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, std::list можно отсортировать с помощью его собственного метода-члена sort(). Использовать общий алгоритм std::sort из <algorithm> для std::list нельзя, так как ему требуются итераторы произвольного доступа, а у list они двунаправленные.

Метод list::sort():

  • Сортирует элементы списка на месте.
  • Выполняет стабильную сортировку (порядок равных элементов сохраняется).
  • Имеет сложность O(N log N).

Примеры использования:

#include <list>
#include <iostream>
#include <functional> // для std::greater

int main() {
    // 1. Сортировка по возрастанию (по умолчанию)
    std::list<int> numbers = {42, 7, 13, 23, 7, 99};
    numbers.sort();
    for (int n : numbers) std::cout << n << ' '; // 7 7 13 23 42 99
    std::cout << 'n';

    // 2. Сортировка по убыванию с использованием компаратора
    numbers.sort(std::greater<int>());
    for (int n : numbers) std::cout << n << ' '; // 99 42 23 13 7 7
    std::cout << 'n';

    // 3. Сортировка пользовательских типов
    struct Person {
        std::string name;
        int age;
        bool operator<(const Person& other) const { return age < other.age; }
    };
    std::list<Person> team = {{"Alice", 30}, {"Bob", 25}, {"Charlie", 35}};
    team.sort(); // Использует operator<
    for (const auto& p : team) std::cout << p.name << ' '; // Bob Alice Charlie
    std::cout << 'n';

    // 4. Сортировка с лямбда-функцией
    team.sort([](const Person& a, const Person& b) {
        return a.name > b.name; // Сортировка по имени в обратном порядке
    });
    for (const auto& p : team) std::cout << p.name << ' '; // Charlie Bob Alice

    return 0;
}

Почему свой метод? std::list реализован как двусвязный список. Его метод sort() обычно реализует алгоритм сортировки слиянием, который эффективно работает со связными структурами, требуя только операций сравнения и перепривязки указателей, без необходимости доступа по индексу.