Глава 6. Стандартная библиотека #
6.2 Алгоритмы STL #
1. Основные алгоритмы из #
Библиотека
Базовые алгоритмы: #
#include <algorithm>
#include <vector>
#include <iostream>
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
// Поиск минимума и максимума
int min_val = *std::min_element(numbers.begin(), numbers.end());
int max_val = *std::max_element(numbers.begin(), numbers.end());
// Подсчет элементов
int count_3 = std::count(numbers.begin(), numbers.end(), 3);
// Заполнение контейнера
std::fill(numbers.begin(), numbers.end(), 0);
// Перемешивание элементов
std::random_shuffle(numbers.begin(), numbers.end());
// Реверс контейнера
std::reverse(numbers.begin(), numbers.end());
Ключевые алгоритмы преобразования: #
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination(source.size());
// Копирование
std::copy(source.begin(), source.end(), destination.begin());
// Преобразование
std::transform(source.begin(), source.end(), destination.begin(),
[](int x) { return x * 2; });
2. Итераторы #
Итераторы — обобщенные указатели для навигации по контейнерам.
Типы итераторов: #
- Input Iterator: Однонаправленный, только чтение
- Output Iterator: Однонаправленная запись
- Forward Iterator: Однонаправленный чтение/запись
- Bidirectional Iterator: Двунаправленный
- Random Access Iterator: Произвольный доступ
std::vector<int> vec = {1, 2, 3, 4, 5};
// Основные операции с итераторами
auto it = vec.begin(); // Итератор на начало
auto end_it = vec.end(); // Итератор на конец
// Перемещение итератора
++it; // Следующий элемент
*it; // Значение по итератору
3. Функциональные объекты (Функторы) #
Функциональные объекты — классы с перегруженным оператором вызова ()
.
// Пример функтора
class Multiplier {
public:
int operator()(int x, int y) const {
return x * y;
}
};
// Использование функтора
Multiplier mult;
int result = mult(4, 5); // result = 20
// Использование с алгоритмами
std::vector<int> numbers = {1, 2, 3, 4, 5};
std::transform(numbers.begin(), numbers.end(), numbers.begin(),
[](int x) { return x * 2; }); // Лямбда как функциональный объект
Стандартные функциональные объекты: #
#include <functional>
std::vector<int> vec = {5, 2, 8, 1, 9};
// Использование стандартных функторов
std::sort(vec.begin(), vec.end(), std::greater<int>());
4. Алгоритмы сортировки #
std::vector<int> numbers = {5, 2, 8, 1, 9, 3};
// Стандартная сортировка
std::sort(numbers.begin(), numbers.end());
// Сортировка с пользовательским компаратором
std::sort(numbers.begin(), numbers.end(),
[](int a, int b) { return a > b; });
// Частичная сортировка
std::partial_sort(numbers.begin(),
numbers.begin() + 3,
numbers.end());
// Сортировка с сохранением стабильности
std::stable_sort(numbers.begin(), numbers.end());
Характеристики сортировок: #
- std::sort: O(n log n), не стабильная
- std::stable_sort: O(n log n), стабильная
- std::partial_sort: Частичная сортировка первых k элементов
5. Алгоритмы поиска #
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// Бинарный поиск (требует отсортированного диапазона)
bool exists = std::binary_search(numbers.begin(), numbers.end(), 5);
// Поиск первого вхождения
auto it = std::find(numbers.begin(), numbers.end(), 5);
if (it != numbers.end()) {
// Элемент найден
size_t index = std::distance(numbers.begin(), it);
}
// Поиск элемента, удовлетворяющего условию
auto pred_it = std::find_if(numbers.begin(), numbers.end(),
[](int x) { return x > 6; });
// Подсчет элементов, удовлетворяющих условию
int count = std::count_if(numbers.begin(), numbers.end(),
[](int x) { return x % 2 == 0; });
Рекомендации по использованию алгоритмов STL #
- Предпочтение алгоритмам STL над ручной реализацией
- Использование лямбда-выражений для кастомизации
- Внимание к сложности алгоритмов
- Проверка совместимости итераторов
- Осторожность с изменением контейнеров во время итерации
Заключение #
Алгоритмы STL предоставляют мощный и эффективный инструментарий для работы с данными. Понимание их возможностей позволяет писать более чистый, производительный и выразительный код.