⚙️ C++

Arrays (listas) em C++17: guia detalhado

STL в C++: vector, map, set и алгоритмы для начинающих

STL (Standard Template Library) — стандартная библиотека шаблонов C++. Это набор готовых контейнеров (структур данных) и алгоритмов, которые избавляют от необходимости писать всё с нуля. STL — одна из главных причин, почему C++ остаётся мощным языком.

vector: динамический массив

vector — самый используемый контейнер STL. Это умный массив, который автоматически изменяет свой размер.

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    // Создание вектора
    vector<int> nums;              // Пустой вектор
    vector<string> words(5);       // 5 элементов (пустые строки)
    vector<int> fixed(3, 42);      // {42, 42, 42}
    vector<int> init = {1,2,3,4,5}; // Инициализация
    
    // Добавление элементов
    nums.push_back(10);
    nums.push_back(20);
    nums.push_back(30);
    
    // Размер
    cout << "Размер: " << nums.size() << endl; // 3
    
    // Доступ по индексу
    cout << nums[0] << endl;         // 10 (без проверки границ)
    cout << nums.at(1) << endl;     // 20 (с проверкой, кидает исключение)
    cout << nums.front() << endl;   // 10 (первый)
    cout << nums.back() << endl;    // 30 (последний)
    
    // Изменение
    nums[0] = 100;
    
    // Удаление последнего
    nums.pop_back();
    cout << "После pop_back: " << nums.size() << endl; // 2
    
    // Вставка по итератору
    nums.insert(nums.begin(), 5);  // Вставить 5 в начало
    
    // Удаление по итератору
    nums.erase(nums.begin());      // Удалить первый
    
    // Перебор
    for (int n : nums) cout << n << " ";
    cout << endl;
    
    // Сортировка
    vector<int> v = {5,2,8,1,9,3};
    sort(v.begin(), v.end());
    for (int n : v) cout << n << " "; // 1 2 3 5 8 9
    cout << endl;
    
    // Обратная сортировка
    sort(v.begin(), v.end(), greater<int>());
    for (int n : v) cout << n << " "; // 9 8 5 3 2 1
    cout << endl;
    
    // Очистить
    v.clear();
    cout << "Пустой: " << v.empty() << endl; // 1
    
    return 0;
}

Алгоритмы STL

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>   // accumulate
using namespace std;

int main() {
    vector<int> v = {5, 2, 8, 1, 9, 3, 7, 4, 6};
    
    // Поиск
    auto it = find(v.begin(), v.end(), 7);
    if (it != v.end()) cout << "Найдено 7 на индексе: " << (it-v.begin()) << endl;
    
    // find_if — поиск с условием
    auto first_gt5 = find_if(v.begin(), v.end(), [](int n){ return n > 5; });
    if (first_gt5 != v.end()) cout << "Первое > 5: " << *first_gt5 << endl; // 8
    
    // Подсчёт
    cout << "Количество 3: " << count(v.begin(), v.end(), 3) << endl; // 1
    cout << "Количество > 5: " << count_if(v.begin(), v.end(), [](int n){ return n>5; }) << endl;
    
    // Минимум и максимум
    auto [minIt, maxIt] = minmax_element(v.begin(), v.end());
    cout << "Min=" << *minIt << ", Max=" << *maxIt << endl; // Min=1, Max=9
    
    // Сумма (из <numeric>)
    int sum = accumulate(v.begin(), v.end(), 0);
    cout << "Сумма: " << sum << endl; // 45
    
    // Произведение
    int product = accumulate(v.begin(), v.end(), 1, multiplies<int>());
    cout << "Произведение: " << product << endl;
    
    // Реверс
    reverse(v.begin(), v.end());
    for (int n : v) cout << n << " ";
    cout << endl;
    
    // Сортировка с лямбдой
    vector<string> words = {"банан","яблоко","груша","абрикос"};
    sort(words.begin(), words.end()); // По алфавиту
    for (auto& w : words) cout << w << " ";
    cout << endl;
    
    sort(words.begin(), words.end(),
         [](const string& a, const string& b){ return a.length() < b.length(); });
    for (auto& w : words) cout << w << " "; // По длине
    cout << endl;
    
    // Удаление дубликатов
    vector<int> dup = {1,2,2,3,3,3,4,5,5};
    sort(dup.begin(), dup.end());
    auto last = unique(dup.begin(), dup.end());
    dup.erase(last, dup.end());
    for (int n : dup) cout << n << " "; // 1 2 3 4 5
    cout << endl;
    
    return 0;
}

map: словарь ключ→значение

#include <iostream>
#include <map>
#include <string>
using namespace std;

int main() {
    // map — отсортированный словарь (всегда в порядке ключей)
    map<string, int> ages;
    
    // Добавление
    ages["Иван"]   = 25;
    ages["Мария"]  = 22;
    ages["Алексей"]= 30;
    ages.insert({"Боб", 28});
    ages.emplace("Катя", 19); // Эффективнее insert
    
    // Доступ
    cout << "Иван: " << ages["Иван"] << endl;       // 25
    // ages["Несуществующий"] создаст запись со значением 0!
    
    // Безопасный доступ
    auto it = ages.find("Мария");
    if (it != ages.end()) {
        cout << "Мария: " << it->second << endl;
    }
    
    // count для проверки существования
    if (ages.count("Боб") > 0)
        cout << "Боб существует" << endl;
    
    // Перебор (всегда в алфавитном порядке ключей!)
    for (const auto& [name, age] : ages) {  // C++17: structured bindings
        cout << name << ": " << age << " лет" << endl;
    }
    
    // Удаление
    ages.erase("Боб");
    cout << "Размер после удаления: " << ages.size() << endl;
    
    // Практика: подсчёт частоты слов
    string text = "java python java go java python c++";
    map<string, int> freq;
    
    // Разбиваем строку на слова
    size_t pos = 0;
    while ((pos = text.find(' ')) != string::npos) {
        freq[text.substr(0, pos)]++;
        text.erase(0, pos+1);
    }
    freq[text]++; // Последнее слово
    
    cout << "
Частота слов:" << endl;
    for (auto& [word, cnt] : freq)
        cout << "  " << word << ": " << cnt << endl;
    
    return 0;
}

set: только уникальные элементы

#include <iostream>
#include <set>
#include <string>
using namespace std;

int main() {
    // set — отсортированное множество без дубликатов
    set<string> cities;
    
    cities.insert("Москва");
    cities.insert("Питер");
    cities.insert("Новосибирск");
    cities.insert("Москва");    // Дубликат — игнорируется
    cities.insert("Питер");     // Тоже дубликат
    
    cout << "Городов: " << cities.size() << endl; // 3
    
    for (const auto& c : cities) cout << c << " "; // В алфавитном порядке!
    cout << endl;
    
    // Проверка наличия
    if (cities.count("Москва")) cout << "Москва есть" << endl;
    if (!cities.count("Лондон")) cout << "Лондона нет" << endl;
    
    // Удаление
    cities.erase("Питер");
    
    // unordered_set: без сортировки, но быстрее (O(1) vs O(log n))
    #include <unordered_set>
    unordered_set<int> fastSet = {5,2,8,1,9,3};
    fastSet.insert(5); // Дубликат, не добавится
    
    // Практика: найти уникальные слова
    string text = "яблоко груша яблоко банан груша апельсин";
    set<string> unique_words;
    size_t pos = 0, prev = 0;
    while ((pos = text.find(' ', prev)) != string::npos) {
        unique_words.insert(text.substr(prev, pos-prev));
        prev = pos + 1;
    }
    unique_words.insert(text.substr(prev));
    
    cout << "Уникальных слов: " << unique_words.size() << endl; // 4
    for (auto& w : unique_words) cout << w << " ";
    cout << endl;
    
    return 0;
}

Работа со строками (string)

#include <iostream>
#include <string>
#include <sstream>  // stringstream
#include <vector>
using namespace std;

int main() {
    string s = "Привет, мир! Как дела?";
    
    cout << s.length() << endl;         // Длина
    cout << s.find("мир") << endl;      // Позиция "мир"
    cout << s.substr(8, 3) << endl;     // "мир" (от позиции 8, длина 3)
    
    // Замена
    string copy = s;
    size_t pos = copy.find("мир");
    if (pos != string::npos) copy.replace(pos, 3, "C++");
    cout << copy << endl; // "Привет, C++! Как дела?"
    
    // Разбиение строки на слова (через stringstream)
    string text = "яблоко груша банан апельсин";
    vector<string> words;
    stringstream ss(text);
    string word;
    while (ss >> word) words.push_back(word);
    
    cout << "Слов: " << words.size() << endl; // 4
    for (auto& w : words) cout << w << " ";
    cout << endl;
    
    // Число в строку и обратно
    string numStr = to_string(42);
    int n = stoi("100");
    double d = stod("3.14");
    
    // Форматирование через ostringstream
    ostringstream oss;
    oss << "Имя: Иван, возраст: " << 25 << ", GPA: " << 4.5;
    string formatted = oss.str();
    cout << formatted << endl;
    
    return 0;
}

Практический пример: менеджер задач

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

struct Task {
    string title;
    int priority;    // 1-5, где 5 — наивысший
    bool done;
    
    Task(string t, int p) : title(t), priority(p), done(false) {}
};

int main() {
    vector<Task> tasks;
    
    // Добавить задачи
    tasks.emplace_back("Выучить vector", 4);
    tasks.emplace_back("Написать Hello World", 5);
    tasks.emplace_back("Изучить классы", 3);
    tasks.emplace_back("Поиграть в игры", 1);
    tasks.emplace_back("Прочитать документацию", 2);
    
    // Сортировка по приоритету (от высокого к низкому)
    sort(tasks.begin(), tasks.end(),
         [](const Task& a, const Task& b){ return a.priority > b.priority; });
    
    cout << "Задачи по приоритету:" << endl;
    for (auto& t : tasks) {
        cout << "  [" << t.priority << "] " << t.title << endl;
    }
    
    // Выполнить первую задачу
    tasks[0].done = true;
    
    // Посчитать незавершённые
    int pending = count_if(tasks.begin(), tasks.end(),
                           [](const Task& t){ return !t.done; });
    cout << "Незавершённых: " << pending << "/" << tasks.size() << endl;
    
    // Удалить завершённые
    tasks.erase(
        remove_if(tasks.begin(), tasks.end(), [](const Task& t){ return t.done; }),
        tasks.end()
    );
    cout << "После удаления выполненных: " << tasks.size() << " задач" << endl;
    
    return 0;
}

Итого: что мы узнали

  • ✅ STL — Standard Template Library: контейнеры + алгоритмы
  • ✅ vector: динамический массив; push_back, pop_back, size(), []
  • ✅ map: отсортированный словарь ключ→значение; [], find(), count()
  • ✅ set: отсортированное множество без дубликатов
  • ✅ unordered_map/set: без сортировки, но O(1) операции
  • ✅ Алгоритмы из <algorithm>: sort, find, count, reverse, unique
  • ✅ Алгоритмы из <numeric>: accumulate для суммы/произведения
  • ✅ Лямбды в алгоритмах: sort(v.begin(),v.end(),[](int a,int b){...})
  • ✅ for (auto& x : container) — range-based for для всех контейнеров
  • ✅ C++17 structured bindings: for (auto& [key, value] : map)