JustCaptain kod-buduschego

Добавить методический материал по двумерным массивам #2

Слито JustCaptain слил(а) llm/change-52ed52 → main · fe9c6c0
1 файл изменён +62

Войди, чтобы оставлять замечания к строкам.

Показать разницуСкрыть разницу
@@ -0,0 +1,62 @@
1 +# Двумерные массивы в C++
2 +
3 +Матрица — таблица значений с индексами строки и столбца. Примеры из жизни: расписание уроков, игровое поле, карта высот и пиксели изображения. В задаче матрица размера `rows × cols` содержит `rows` строк и `cols` столбцов; индексы начинаются с нуля.
4 +
5 +## Простое представление: вектор векторов
6 +
7 +```cpp
8 +int rows, cols;
9 +std::cin >> rows >> cols;
10 +std::vector<std::vector<int>> a(rows, std::vector<int>(cols));
11 +for (int r = 0; r < rows; ++r)
12 + for (int c = 0; c < cols; ++c)
13 + std::cin >> a[r][c];
14 +```
15 +
16 +Обращение `a[r][c]` читается как «строка r, столбец c». Для квадратной матрицы `rows == cols`, для прямоугольной — размеры могут отличаться. Нельзя предполагать квадратность, если это не сказано в условии. Вложенный вектор позволяет строкам иметь разную длину, но каждая внутренняя строка — отдельный `vector`, поэтому вся матрица не обязательно лежит в одном непрерывном блоке памяти.
17 +
18 +## Плоское хранение
19 +
20 +Для прямоугольной матрицы можно хранить значения в одном векторе длины `rows * cols`. Элемент `(r,c)` лежит по индексу `r * cols + c`:
21 +
22 +```cpp
23 +std::vector<int> a(static_cast<std::size_t>(rows) * cols);
24 +a[static_cast<std::size_t>(r) * cols + c] = value;
25 +```
26 +
27 +Это хранение единым буфером: удобно для больших матриц и алгоритмов, которым важна непрерывность памяти. Формула использует число столбцов, не строк. Прежде чем выделять память, проверьте допустимость размеров и риск переполнения при их перемножении.
28 +
29 +## Обходы
30 +
31 +Обычный обход по строкам:
32 +
33 +```cpp
34 +for (int r = 0; r < rows; ++r) {
35 + for (int c = 0; c < cols; ++c) {
36 + // обработать a[r][c]
37 + }
38 +}
39 +```
40 +
41 +Так элементы читаются в естественном для C++ порядке хранения. Сумма всех элементов стоит `O(rows * cols)`. Обход соседей клетки используйте только после проверки границ: `0 <= nr < rows` и `0 <= nc < cols`. Для направлений часто заводят массивы `dr = {-1, 1, 0, 0}` и `dc = {0, 0, -1, 1}`.
42 +
43 +## Память и алгоритмическая сложность
44 +
45 +Матрица из `R*C` значений занимает `O(R*C)` памяти. Если задачу можно решить построчно, храните только необходимые строки — иногда дополнительную память удаётся уменьшить с `O(R*C)` до `O(C)`. Например, при вычислении каждой строки динамического программирования могут быть нужны только предыдущая и текущая строки. Различайте память самой входной матрицы и дополнительную память алгоритма.
46 +
47 +Поворот или транспонирование матрицы обычно требуют либо нового буфера `O(R*C)`, либо аккуратных операций на месте. Квадратную матрицу можно транспонировать на месте, меняя местами `a[r][c]` и `a[c][r]` только для `c > r`. Для прямоугольной матрицы размеры меняются местами, поэтому простое такое правило не подходит.
48 +
49 +## Сравнение языков
50 +
51 +Python часто представляет таблицу как список списков: `grid[r][c]`. Создавая матрицу, не используйте `[[0] * cols] * rows`: все строки окажутся ссылками на один и тот же список. Используйте `[[0 for _ in range(cols)] for _ in range(rows)]`.
52 +
53 +Rust обычно использует `Vec<Vec<T>>` или плоский `Vec<T>` с индексом `r * cols + c`. Как и в C++, вложенные векторы удобны для строк, а плоский буфер — для одного непрерывного блока. Rust дополнительно проверяет владение и заимствования; C++ программист сам отвечает за границы и время жизни ссылок. У `vector<vector<T>>` внешний `vector` владеет строками, у плоского `vector` — единым хранилищем.
54 +
55 +## Частые ошибки
56 +
57 +- Перепутаны `rows` и `cols`, особенно при транспонировании.
58 +- Цикл идёт до `<= rows` вместо `< rows`.
59 +- Индекс вычислен как `c * rows + r`, хотя правильная формула для построчного хранения — `r * cols + c`.
60 +- Доступ к соседу происходит до проверки его координат.
61 +- Создана матрица с `rows * cols`, но произведение переполнилось или объём слишком велик.
62 +- В Python строки матрицы случайно разделяют один список.