В вычислительной технике группа параллельных массивов (также известная как структура массивов или SoA) — это форма неявной структуры данных , которая использует несколько массивов для представления единственного массива записей . Она хранит отдельный однородный массив данных для каждого поля записи, каждый из которых имеет одинаковое количество элементов. Затем объекты, расположенные по одному индексу в каждом массиве, неявно являются полями одной записи. Указатели с одного объекта на другой заменяются индексами массива. Это контрастирует с обычным подходом хранения всех полей каждой записи вместе в памяти (также известным как массив структур или AoS). Например, можно объявить массив из 100 имен, каждое из которых является строкой, и 100 возрастов, каждое из которых является целым числом, связывая каждое имя с возрастом, имеющим тот же индекс.
Пример на языке C с использованием параллельных массивов:
int ages [] = { 0 , 17 , 2 , 52 , 25 }; char * names [] = { "Нет" , "Майк" , "Билли" , "Том" , "Стэн" }; int parent [] = { 0 /*Нет*/ , 3 /*Том*/ , 1 /*Майк*/ , 0 /*Нет*/ , 3 /*Том*/ }; for ( i = 1 ; i <= 4 ; i ++ ) { printf ( "Имя: %s, Возраст: %d, Родитель: %s \n " , имена [ i ], возраст [ i ], имена [ родитель [ i ]]); }
в Perl (используя хэш массивов для хранения ссылок на каждый массив):
мои %данные = ( first_name => [ 'Джо' , 'Боб' , 'Фрэнк' , 'Ганс' ], last_name => [ 'Смит' , 'Сегер' , 'Синатра' , 'Шульце' ], height_in_cm => [ 169 , 158 , 201 , 199 ]); для $i ( 0 .. $# { $data { first_name }}) { printf "Имя: %s %s\n" , $data { first_name }[ $i ], $data { last_name }[ $i ]; printf "Рост в см: %i\n" , $data { height_in_cm }[ $i ]; }
Или на Python :
first_names = [ "Джо" , "Боб" , "Фрэнк" , "Ганс" ] last_names = [ "Смит" , "Сегер" , "Синатра" , "Шульце" ] heights_in_cm = [ 169 , 158 , 201 , 199 ]для i в диапазоне ( len ( first_names )): print ( "Имя: %s %s " % ( first_names [ i ], last_names [ i ])) print ( "Рост в см: %s " % heights_in_cm [ i ]) # Использование zip: для first_name , last_name , height_in_cm в zip ( first_names , last_names , heights_in_cm ): print ( f "Имя: { first_name } { last_name } " ) print ( f "Рост в см: { height_in_cm } " )
Параллельные массивы имеют ряд практических преимуществ по сравнению с обычным подходом:
Некоторые из этих преимуществ в значительной степени зависят от конкретного языка программирования и используемой реализации.
Однако параллельные массивы также имеют несколько существенных недостатков, что объясняет, почему они, как правило, не являются предпочтительными:
Плохая локальность ссылок может быть смягчена в некоторых случаях: если структуру можно разделить на группы полей, к которым обычно обращаются вместе, массив может быть построен для каждой группы, а его элементы будут записями, содержащими только эти подмножества полей большей структуры. (см. проектирование, ориентированное на данные ). Это ценный способ ускорить доступ к очень большим структурам со многими членами, сохраняя при этом части структуры связанными вместе. Альтернативой связыванию их вместе с помощью индексов массива является использование ссылок для связывания частей вместе, но это может быть менее эффективно во времени и пространстве.
Другой альтернативой является использование одного массива, где каждая запись является структурой записи. Многие языки предоставляют способ объявлять реальные записи и массивы из них. В других языках может быть целесообразно имитировать это, объявляя массив размером n*m, где m — размер всех полей вместе, упаковывая поля в то, что фактически является записью, даже если в конкретном языке отсутствует прямая поддержка записей. Некоторые оптимизации компилятора , особенно для векторных процессоров , способны выполнять это преобразование автоматически, когда массивы структур создаются в программе. [ необходима цитата ]