Ключ к организации структуры
состоит в указании способа доступа к элементам
сруктуры. Это, в свою очередь, определяет, как
надо формировать массив записей и его поля. Рассмотрим
RGB-изображение размером 128x128 пикселей, записанное
в трех массивах: RED, GREEN, BLUE:
Рис. 6.4
Имеются, по крайней мере, два способа
организации этих данных в структуру, как это
показано на рис. 6.5 а, б.
а)
б)
Рис. 6.5
Матричная организация. В этом случае
каждое поле структуры - это массив координат
точек одного цвета. Такую структуру можно
создать, используя следующие присваивания
A.r = RED;
A.g = GREEN;
A.b = BLUE;
Этот подход позволяет выделить целые массивы
для отображения, фильтрации или выполнения
других функций над изображением. В этом случае,
чтобы получить доступ к множеству точек красного
цвета, надо всего лишь воспользоваться
присваиванием
red_plane = A.red;
Матричная организация имеет преимущества при
работе со множеством изображений, когда эти
изображения можно накопить в виде массивов A(2),
A(3), ….. , содержащих целые образы.
Недостаток такой организации очевиден, когда
требуется получить доступ к подмассиву массива
цветов. Для того чтобы получить доступ к
подобразу, необходимо получить доступ к
определенным участкам поля структуры, например,
таким
red_sub = A.r(2:12, 13:30);
grn_sub = A.g(2:12, 13:30);
blue_sub = A.b(2:12, 13:30);
Поэлементная организация. В этом
случае определение отдельных элементов данных
реализуется в виде циклов
for i = 1:size(RED, 1)
for j = 1:size(RED, 2)
B(i, j).r = RED(i, j);
B(i, j).g = GREEN(i, j);
B(i, j).b = BLUE(i, j);
end
end
При такой организации доступ к подмножеству
данных может быть выполнен с помощью оператора
присваивания
Bsub = B(1:10,1:10); .
Однако, чтобы получить доступ к матрице,
требуется организовать цикл:
red_plane = zeros(128, 128);
for i = 1:(128*128)
red_plane(i) = B(i).r;
end
Поэлементная организация - не лучший выбор для
приложений, связанных с обработкой изображений;
однако он может оказаться предпочтительным,
когда необходим доступ к отдельным участкам
полей.
Следующий пример демонстрирует преимущества
такого подхода.
Пример.
Рассмотрим следующие два варианта организации
базы данных (рис.6.6):
а)
б)
Рис. 6.6
Каждая из них имеет свои преимущества и
недостатки:
- Матричная организация позволяет упростить
обработку полей данных.
Пример.
Нахождение среднего всех значений поля amount
реализуется следующим образом:
в случае матричной организации:
avg =
mean(A.amount);
в случае поэлементной
организации:
avg =
mean([B.amount]);
- Поэлементная организация позволяет упростить
доступ к полям, связанным с отдельной записью.
Пример.
Рассмотрим М-файл client.m, который выводит на
экран имя и адрес клиента.
- в случае
матричной организации надо отображать
индивидуальные поля:
function client(name,
address)
disp(name)
disp(address)
- в случае
поэлементной организации можно отобразить целую
запись:
function client(B)
disp(B)
Вызов функции client должен быть организован
следующим образом:
- в случае
матричной организации:
client(A.name(2,:),A.address(2,:))
- в случае
поэлементной организации:
client(B(2))
Поэлементная организация упрощает работу со
строками переменной длины. В случае матричной
организации, если априори неизвестна
максимальная длина строки, придется многократно
определять размеры полей name или address, чтобы
разместить более длинные строки.
Обычно сами данные не диктуют выбор схемы
организации; ее определяют операции доступа и
обработки данных.
Вложенные структуры
Поле структуры может само включать другую
структуру или даже массив структур. Как только
структура создана, с помощью операторов
присваивания или функции struct можно вложить
структуры в существующие поля.
Применение функции struct. Чтобы
сформировать вложенную структуру, необходимо
организовать рекурсию при вызове функции struct.
Пример.
Допустим, что требуется создать структуру
размера 1х2. Организуем следующий рекурсивный
вызов функции struct:
A = struct('data',[3 4 7; 8 0
1],'nest',...
struct('testnum','Test
1','xdata',[4 2 8],'ydata',[7 1 6]))
A =
data: [2x3 double]
nest: [1x1 struct]
Запись A(1) содержит требуемые значения,
благодаря вызову внешней функции struct.
Следующая последовательность операторов
производит результат, аналогичный предыдущему:
A(1).data = [3 4 7; 8 0 1];
A(1).nest.testnum = 'Test 1';
A(1).nest.xdata = [4 2 8];
A(1).nest.ydata = [7 1 6];
A(2).data = [9 3 2; 7 6 5];
A(2).nest.testnum = 'Test 2';
A(2).nest.xdata = [3 4 2];
A(2).nest.ydata = [5 0 9]
A =
1x2 struct array
with fields:
data
nest
Введем изменения в запись A(2):
A(2).data = [9 3 2; 7 6 5];
A(2).nest.testnum = 'Test 2';
A(2).nest.xdata = [3 4 2];
A(2).nest.ydata = [5 0 9]
A =
1x2 struct
array with fields:
data
nest
Тогда получим следующую структуру:
Рис. 6.7
Как и в случае массивов записей с одним уровнем
вложения, можно с использованием операторов
присваивания сформировать вложенные массивы
структур.
Индексация вложенных структур. Для
того чтобы проиндексировать структуру, надо
добавить имена вложенных полей, используя в
качестве разделителя точку (.). Первая текстовая
строка индексного выражения определяет имя
структуры, а последующие имена полей, содержащих
другие структуры.
Пример.
Вышеописанный массив A имеет 2 уровня
вложенности:
- для получения доступа к вложенной структуре
внутри A(1) надо использовать A(1).nest.
- для получения доступа к полю xdata вложенной
структуры внутри A(1) надо использовать A(2).nest.xdata.
- для получения доступа к элементу 2 поля ydata
вложенной структуры внутри A(1) надо использовать
A(1).nest.ydata(2).
Многомерные массивы структур
Многомерные массивы структур рассматриваются
как расширение прямоугольных массивов структур.
По аналогии с другими типами многомерных
массивов их можно формировать, либо используя
операторы присваивания, либо функцию cat.
Пример.
Сформируем многомерный массив структур
следующего вида, используя операторы
присваивания (рис. 6.8):
patient(1, 1, 1).name = 'John
Doe';patient(1,1,1).billing = 127.00;
patient(1, 1, 1).test = [79 75 73; 180 178 177.5; 220
210 205];
patient(1, 2, 1).name = 'Ann
Lane';patient(1,2,1).billing = 28.50;
patient(1, 2, 1).test = [68 70 68; 118 118 119; 172
170 169];
patient(1, 1, 2).name = 'Al
Smith';patient(1,1,2).billing = 504.70;
patient(1, 1, 2).test = [80 80 80; 153 153 154; 181
190 182];
patient(1, 2, 2).name = 'Dora
Jones';patient(1,2,2).billing =1173.90;
patient(1, 2, 2).test = [73 73 75; 103 103 102; 201
198 200];
Рис. 6.8. Многомерный массив структур
размера 1х2х2.
Для применения функций к многомерным массивам
структур надо использовать индексный подход,
чтобы получить доступ к полям записи и элементам
полей.
Пример.
Вычислить сумму значений столбцов массива test
для структуры patient(1, 1, 2):
sum((patient(1,
1, 2).test))
ans =
414 423 416
Суммировать все поля billing 3-мерного массива
структур patient:
total =
sum([patient.billing])
total =
1834.10
|