Массив — базовая структура данных: упорядоченная коллекция элементов, доступ к которым осуществляется по индексу. Проще представить как ряд ячеек в памяти, каждой присвоен номер. Это делает чтение и запись быстрыми и предсказуемыми.
Ключевые свойства
- Доступ по индексу за константное время O(1).
- Вставка или удаление внутри массива требует сдвига элементов и стоит O(n) в худшем случае.
- Фиксированная или динамическая длина — зависит от реализации в языке.
- Хранение соседних элементов в смежных ячейках памяти полезно для кеша процессора.
Как создают массивы в разных языках
Ниже — короткие примеры. Они показывают как один концепт выглядит по-разному в синтаксисе.
// C: статический массив
int a[5] = {1, 2, 3, 4, 5};
// Java: массив фиксированной длины
int[] b = new int[]{1, 2, 3};
// JavaScript: динамический массив (Array)
let c = [1, 2, 3];
c.push(4);
// Python: список — динамический массив по сути
lst = [1, 2, 3]
lst.append(4)
Частые операции
- Чтение/запись: a[i] — быстро.
- Перебор: for или итераторы; эффективен для последовательных проходов.
- Добавление в конец: в динамических массивах амортизированно O(1).
- Вставка в середину/удаление: требует сдвига, O(n).
- Копирование: глубокое или поверхностное — важно понимать поведение при ссылочных типах.
Многомерные массивы
Двумерный массив — матрица. В языках низкого уровня это просто последовательность последовательностей в памяти. Важно различать «реальную» матрицу (смежная память) и массив массивов (каждая строка хранится отдельно).
// Python: список списков
matrix = [
[1, 2, 3],
[4, 5, 6]
]
// NumPy: эффективная смежная матрица для чисел
import numpy as np
m = np.array(matrix)
Подводные камни и ошибки
- Выход за границы индекса — частая ошибка. Проверяйте длину перед доступом.
- Поверхностное копирование списков и массивов ссылочных объектов приводит к неожиданным разделяемым изменениям.
- В языках с нулевой инициализацией (C) неопределённые значения могут привести к багам.
- Сравнение массивов: сравнивать по содержимому, а не по ссылке, когда это важно.
- В JavaScript пустые слоты в разреженных массивах ведут себя неинтуитивно при переборе.
Когда выбрать массив, а когда нет
Массив — отличное решение, если важна быстрая индексация и предсказуемая память. Если же нужны частые вставки/удаления в середине, стоит посмотреть в сторону связных списков, деревьев или специализированных структур. Когда важна автоматическая перераспределённость размера, выбирайте динамический массив (vector, ArrayList, list в Python).
Практические советы
- Для больших числовых массивов используйте специализированные библиотеки (NumPy, TypedArray в JavaScript) — они экономят память и ускоряют вычисления.
- Четко различайте копию массива и ссылку на массив. В Python copy() или slicing [:] дают поверхностную копию, deepcopy — глубокую.
- Избегайте частых операций вставки в начало массива; лучше накапливать данные и делать одну большую операцию или использовать deque.
- Профилируйте: иногда замена массива на другую структуру значительно улучшает производительность в реальной задаче.
Короткое резюме
Массив — простой и мощный инструмент. Он экономит время при чтении по индексу и хорошо подходит для последовательных данных. Помните о сложностях при вставках и копировании и выбирайте реализацию, соответствующую задаче.