
Массив — базовая структура данных: упорядоченная коллекция элементов одного или разных типов, доступ к которым выполняется по целому индексу. Это не магия, а простой механизм, который лежит в основе множества алгоритмов и библиотек.
Как устроен массив
В традиционной реализации массив занимает подряд идущие ячейки памяти. Индекс i переводится в адрес по формуле base + i * size, где size — размер одного элемента. Такая организация даёт быстрый доступ по индексу за постоянное время.
Типичные операции и их сложность
- Доступ по индексу: O(1)
- Добавление в конец (в статическом массиве) — нельзя; в динамическом — амортизированно O(1)
- Вставка или удаление в середине: O(n) из‑за сдвига
- Поиск неупорядоченного элемента: O(n)
- Поиск в отсортированном массиве (бинарный): O(log n)
Статический vs динамический
Статический массив выделяется с фиксированным размером. Это предсказуемо по памяти и быстро. Динамический расширяет размер автоматически, обычно удваивая ёмкость, но при расширении выполняется дорогостоящая копия данных. Выбор зависит от требований к памяти и от частоты изменений размера.
Примеры кода
JavaScript: удобный, но типы элементов не фиксированы.
const arr = [1, 2, 3];
arr.push(4); // добавление в конец
const x = arr[1]; // доступ по индексу
arr.splice(2, 1); // удаление элемента
Python: гибкая семантика, много встроенных методов.
arr = [1, 2, 3]
arr.append(4)
x = arr[1]
arr.pop(2)
C: низкоуровневый контроль и явное управление памятью.
int *a = malloc(n * sizeof(int));
a[0] = 10;
free(a);
Распространённые ошибки
- Выход за границы индекса. Частая причина краха программы.
- Ошибочные предположения о времени вставки в середину. Она требует сдвига элементов.
- Неучтённые копии при передаче по значению — большие массивы становятся дорогостоящими.
- Неправильная работа с указателями в языках без сборщика мусора.
Когда массив — хорошее решение
Массив подходит, когда нужен быстрый доступ по индексу, известен или ограничен размер, и операции в основном чтение или добавление в конец. Для частых вставок и удалений в произвольных местах лучше рассмотреть другие структуры.
Альтернативы
- Динамический массив / вектор — удобен, если размер меняется.
- Связный список — эффективен для частых вставок/удалений в середине, но медленнее по доступу по индексу.
- Дек — быстрая вставка/удаление с обоих концов.
- Множества и хеш-таблицы — для быстрой проверки вхождения без упорядочивания.
Практические советы
- Если заранее знаете размер, выделите память сразу — это экономит копии и фрагментацию.
- При частых расширениях полезно увеличивать ёмкость не на единицу, а умножать на константу, например на 1.5–2.
- Избегайте частых операций вставки в середину в больших массивах; пересмотрите выбор структуры.
- Используйте встроенные методы языка: они обычно оптимизированы и безопасны.
Массив прост, но мощен. Понимание его характеристик помогает принимать правильные архитектурные решения и писать код, который работает быстро и предсказуемо.