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

Ответ

Да, 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() обычно реализует алгоритм сортировки слиянием, который эффективно работает со связными структурами, требуя только операций сравнения и перепривязки указателей, без необходимости доступа по индексу.

Ответ 18+ 🔞

Э, слушай, а вот этот твой std::list... Его же тоже можно отсортировать, да? Не то чтобы это было прям очевидно, как с вектором. Так вот, да, можно, но только своим, специальным методом sort(). Потому что если ты попробуешь тупо взять общий std::sort из <algorithm> и сунуть ему твой список — он тебе такого наговорит, что ты сам от себя охуеешь. А всё почему? Потому что этому общему алгоритму подавай итераторы произвольного доступа, а у списка они, блядь, только двунаправленные. Так что не выйдет, чувак.

Вот про метод 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 — это же, ёпта, двусвязный список. Его внутренняя сортировка (чаще всего — слиянием) заточена под эту структуру. Ей не нужны прыжки по индексам, ей нужно только сравнивать элементы и аккуратно перекидывать указатели. Так что всё логично, просто запомни: для списка — только list.sort(), и будет тебе счастье.