Массив — одна из базовых структур данных. По сути это набор элементов одного типа, расположенных в памяти подряд и доступных по индексу. Простота не мешает массиву быть в основе многих алгоритмов и более сложных структур.
Что важно знать в начале
- Индексация обычно начинается с нуля: первый элемент имеет индекс 0.
- Доступ к элементу по индексу выполняется за константное время, то есть очень быстро.
- Массивы бывают статическими и динамическими. В статическом размере фиксированы, в динамическом — можно расширять.
Типы массивов
- Одномерный — просто список значений: [a0, a1, a2, …].
- Двумерный и многомерный — таблицы и их обобщения.
- Зубчатые (jagged) массивы — массив массивов, где длина вложенных массиво́в может отличаться.
Базовые операции и их сложность
- Чтение/запись по индексу: O(1).
- Поиск по значению при полном проходе: O(n).
- Вставка или удаление в середине: O(n) — потому что нужно сдвинуть элементы.
- Добавление в конец у динамических массивов: амортизированно O(1); при переполнении — копирование всего массива.
Как массив хранится в памяти
Низкоуровневые массивы размещаются непрерывно: элементы идут подряд. Это даёт экономию памяти и преимущества в кэшировании. Но именно непрерывность делает вставки и удаления затратными, если речь о середине коллекции.
Примеры использования
Массивы подходят для хранения упорядоченных наборов: последовательности значений, таблицы, буферы. Их используют при реализации сортировок, при работе с матрицами, при хранении данных, которые нужно быстро читать по индексу.
Короткие примеры кода
Синтаксис разный, идея одна. Здесь примеры, чтобы увидеть различия.
// C: статический массив и доступ
int a[5] = {10, 20, 30, 40, 50};
int x = a[2]; // 30
# Python: список как динамический массив
a = [10, 20, 30, 40, 50]
x = a[2] # 30
a.append(60) # добавление в конец
a.insert(2, 25) # вставка в середину (сдвиг элементов)
// JavaScript: массивы гибкие
let a = [10, 20, 30];
a.push(40); // добавить в конец
a.splice(1, 0, 15);// вставить 15 на позицию 1
// Java: одномерный и двумерный массив
int[] a = {10,20,30};
int[][] m = {{1,2,3},{4,5,6}};
int x = m[1][2]; // 6
Практические советы
- Если нужны частые вставки и удаления в середине — рассмотрите связный список или дек.
- Когда важна быстрая проверка наличия элемента и порядок не обязателен, используйте хеш-структуры.
- Для больших объёмов данных учитывайте размер элемента: чем он больше, тем быстрее растут затраты при копировании.
- Если доступ по индексу важнее всего, массив — лучший выбор.
Распространённые ошибки
- Выход за границы массива — частая причина ошибок и падений программы.
- Неправильное предположение о начальной индексации: в некоторых языках (например, Fortran, MATLAB) индексация начинается с 1.
- Ожидание, что массив автоматически оптимизирует вставки в середине — не так.
Итог
Массив — это сочетание скорости доступа и простоты. Он не универсален, но там, где нужен быстрый доступ по индексу и предсказуемая модель памяти, массив остаётся лучшим выбором. Зная его сильные и слабые стороны, можно подобрать правильную структуру для конкретной задачи и избежать типичных ошибок.