
Массив — это структура данных, которую вы встретите в любой культуре программистов. По сути, это упорядоченный набор элементов одного типа, хранящийся в памяти подряд. Такой простой принцип даёт сильные преимущества: быстрый доступ, компактное хранение и предсказуемое поведение.
Что важно знать о массивах
- Память и порядок. Элементы массива располагаются последовательно, поэтому адрес i-го элемента вычисляется по формуле base + i * size. Это даёт доступ по индексу за постоянное время.
- Доступ по индексу. Чтение или запись значения по индексу занимает O(1), то есть время не зависит от размера массива.
- Вставки и удаления. Добавление или удаление в середине требует сдвига элементов, что занимает O(n). Вставка в конец динамического массива обычно амортизированно O(1) благодаря увеличению ёмкости сразу на несколько элементов при переполнении.
- Однородность типов. В языках со строгой типизацией массивы обычно содержат элементы одного типа. В динамических языках один массив может хранить разные типы, но внутренне это реализуется иначе, чем в языках с плотным представлением.
Статические и динамические массивы
Статический массив фиксирует размер при выделении. Это экономно по памяти и просто по реализации, но неудобно, если заранее неизвестен объём данных. Динамический массив позволяет менять размер логически, при необходимости расширяя внутренний буфер. Типичная стратегия расширения — умножение ёмкости на константу, например 1.5 или 2, чтобы избежать частых перераспределений.
Многомерные массивы
Двух- и большемерные массивы — просто однотипные массивы массивов, но важно помнить о порядке хранения. В C и сходных языках массивы хранятся в порядке строк, то есть соседние элементы по горизонтали идут подряд. В других языках, например Fortran, порядок иной. Это влияет на производительность при большом объёме данных, потому что работа с соседними элементами экономит кеш-память.
Сравнение с другими структурами
- Массив vs связный список: массив быстрее по доступу по индексу и пообщему расположению в памяти, список эффективнее при частых вставках и удалениях в середине, если неважен случайный доступ.
- Массив vs хеш-таблица: массив хорош для компактного хранения и индексации по числовому индексу. Если нужно маппинг по ключам, хеш-таблица или словарь подходят лучше.
Примеры кода
Короткие примеры показывают, как выглядят массивы в популярных языках.
// C: статический массив
int a[5] = {1, 2, 3, 4, 5};
a[2] = 10; // доступ по индексу O(1)
// C++: динамический массив (std::vector)
#include
std::vector v = {1,2,3};
v.push_back(4); // амортизированно O(1)
v.insert(v.begin() + 1, 9); // O(n)
// Python: список как динамический массив
a = [1, 2, 3]
a.append(4) # амортизированно O(1)
a.insert(1, 10) # O(n)
// JavaScript: массивы с гибкой типизацией
let arr = [1, "two", true];
arr.push(4);
console.log(arr[1]); // O(1)
Практические советы
- Если нужен быстрый доступ по индексу и предсказуемое использование памяти — выбирайте массивы.
- Для больших объёмов данных думайте о порядке доступа. Проход по строкам в двумерном массиве будет быстрее, если данные хранятся строко-ориентированно.
- Когда часто вставляете в начало или в середину и порядок не критичен, рассмотрите двусвязный список или специализированные структуры.
- При необходимости частого увеличения размера заранее резервируйте ёмкость, если язык это поддерживает, чтобы избежать дорогих копирований.
Заключение
Массив — это не просто набор данных, он задаёт профиль производительности вашей программы. Поняв, как устроена память и какие операции обходятся дорого, вы сможете принимать обоснованные архитектурные решения. Массивы просты, но их поведение важно учитывать всегда, когда требуется скорость и компактность хранения.