8 多維數組
在實際應用的過程中,經常需要構造多於二維的數組,我們將多於二維的數組統稱為多維數組。
對於二維數組,人們習慣於把數組的第1維稱為「行」,把第2維稱為「列」,我們將第3維稱為「頁」。
由於更多維的數組的顯示並不直觀,所以本節以三維數組為例來介紹多維數組的使用。
8.1 多維數組的創建
創建多維數組最常用的方法有以下4種。
(1)直接通過「全下標」元素賦值的方式創建多維數組。
(2)由若干同樣尺寸的二維數組組合成多維數組。
(3)由函數ones、zeros、rand、randn等直接創建特殊多維數組。
(4)藉助cat、repmat、reshape等函數構建多維數組。
【例2-26】 採用「全下標」元素賦值方式創建多維數組示例。
>> A(3,3,3)=1 % 創建3*3*3數組,未賦值元素默認設置為0
A(:,:,1) =
0 0 0
0 0 0
0 0 0
A(:,:,2) =
0 0 0
0 0 0
0 0 0
A(:,:,3) =
0 0 0
0 0 0
0 0 1
>> B(3,4,:)=1:4 % 創建3*4*4數組
B(:,:,1) =
0 0 0 0
0 0 0 0
0 0 0 1
B(:,:,2) =
0 0 0 0
0 0 0 0
0 0 0 2
B(:,:,3) =
0 0 0 0
0 0 0 0
0 0 0 3
B(:,:,4) =
0 0 0 0
0 0 0 0
0 0 0 4
【例2-27】 由二維數組合成多維數組示例。
>> clear
>> A(:,:,1)=magic(4); % 創建數組A第1頁的數據
>> A(:,:,2)=ones(4); % 創建數組A第2頁的數據
>> A(:,:,3)=zeros(4) % 創建數組A第3頁的數據
A(:,:,1) =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
A(:,:,2) =
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
A(:,:,3) =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
【例2-28】 由函數rand直接創建特殊多維數組示例。
>> rand('state', 0); % 設置隨機種子,便於讀者驗證
>> B=rand(3,4,3)
B(:,:,1) =
0.9501 0.4860 0.4565 0.4447
0.2311 0.8913 0.0185 0.6154
0.6068 0.7621 0.8214 0.7919
B(:,:,2) =
0.9218 0.4057 0.4103 0.3529
0.7382 0.9355 0.8936 0.8132
0.1763 0.9169 0.0579 0.0099
B(:,:,3) =
0.1389 0.6038 0.0153 0.9318
0.2028 0.2722 0.7468 0.4660
0.1987 0.1988 0.4451 0.4186
【例2-29】 藉助cat函數構建多維數組示例。
>>B=cat(3,ones(2,3),ones(2,3)*2,ones(2,3)*3)
B(:,:,1) =
1 1 1
1 1 1
B(:,:,2) =
2 2 2
2 2 2
B(:,:,3) =
3 3 3
3 3 3
cat指令第1個輸入變量填寫的數字「表示擴展方向的維號」。本例第1個輸入變量是3,表示「沿第3維方向擴展」。為了對比下面我們分別演示使用cat函數沿其他方向進行擴展的情況。
>>B=cat(2,ones(2,3),ones(2,3)*2,ones(2,3)*3) % 沿第2維方向擴展
B =
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
>>B=cat(1,ones(2,3),ones(2,3)*2,ones(2,3)*3) % 沿第1維方向擴展
B =
1 1 1
1 1 1
2 2 2
2 2 2
3 3 3
3 3 3
>>B=cat(4,ones(2,3),ones(2,3)*2,ones(2,3)*3) % 沿第4維方向擴展
B(:,:,1,1) =
1 1 1
1 1 1
B(:,:,1,2) =
2 2 2
2 2 2
B(:,:,1,3) =
3 3 3
3 3 3
【例2-30】 藉助repmat函數構建多維數組示例。
>> repmat([1,2;3,4;5,6],[1,2,3])
ans(:,:,1) =
1 2 1 2
3 4 3 4
5 6 5 6
ans(:,:,2) =
1 2 1 2
3 4 3 4
5 6 5 6
ans(:,:,3) =
1 2 1 2
3 4 3 4
5 6 5 6
repmat函數的第1個輸入變量是構成多維數組的源數組。第2個輸入變量是指定向各維方向上擴展的源數組個數。本例中輸入變量[1,2,3]是指將源數組在行方向上擴展為1個,在列方向上擴展為2個,在頁方向上擴展為3個。
【例2-31】 藉助reshape函數構建多維數組示例。
>> A=reshape(1:60,5,4,3)
A(:,:,1) =
1 6 11 16
2 7 12 17
3 8 13 18
4 9 14 19
5 10 15 20
A(:,:,2) =
21 26 31 36
22 27 32 37
23 28 33 38
24 29 34 39
25 30 35 40
A(:,:,3) =
41 46 51 56
42 47 52 57
43 48 53 58
44 49 54 59
45 50 55 60
>> B=reshape(A,4,5,3)
B(:,:,1) =
1 5 9 13 17
2 6 10 14 18
3 7 11 15 19
4 8 12 16 20
B(:,:,2) =
21 25 29 33 37
22 26 30 34 38
23 27 31 35 39
24 28 32 36 40
B(:,:,3) =
41 45 49 53 57
42 46 50 54 58
43 47 51 55 59
44 48 52 56 60
reshape的第1個輸入變量是源數組,第2、3、4個輸入變量是要生成的數組的行數、列數和頁數。將要生成的數組必須和源數組的元素的個數相同。重組時,元素排列遵循「單下標」編號規則:第1頁的第1列接該頁的第2列,直至第1頁最後一列。在第1頁排列結束後,開始排列第2頁的第1列,依次類推,直至所有的元素排列結束。
8.2 多維數組的尋訪與重構
1.多維數組的尋訪
多維數組的尋訪和二維數組一樣,可以使用「全下標」、「單下標」和「邏輯下標」來尋訪。「全下標」和「邏輯下標」兩種形式與二維數組相同,是以非常直觀的形式來表現的,這裡不再贅述。而多維數組的「單下標」就比較複雜一點。本小節對此進行介紹。
多維數組的「單下標」其實就是二維數組「單下標」的擴展,換句話說,二維數組的「單下標」編排方式是「單下標」的一種簡單形式。用語言表示就是:將數組「全下標」格式中的各維按照出現的先後順序依次循環,直至將所有的數據編排成為一列。
【例2-32】 多維數組「單下標」排列示例。
>> a=ones(2,2,2,2) % 創建全為1的2*2*2*2四維數組a
a(:,:,1,1) =
1 1
1 1
a(:,:,2,1) =
1 1
1 1
a(:,:,1,2) =
1 1
1 1
a(:,:,2,2) =
1 1
1 1
>> a(1:16)=1:16 % 按照單下標形式為數組a賦值
a(:,:,1,1) =
1 3
2 4
a(:,:,2,1) =
5 7
6 8
a(:,:,1,2) =
9 11
10 12
a(:,:,2,2) =
13 15
14 16
從得到結果中的數組a被賦值以後的各元素分布,可以看出多維數組是如何按照「全下標」的各維順序來存儲數據的。
2.多維數組的重構
除了前面介紹的可以用來進行多維數組的重構函數cat、repmat和reshape之外,還有其他一些函數可用來進行多維數組的重構,詳見表2-10。
表2-10 多維數組重構函數
函數形式
函數功能
函數形式
函數功能
permute
廣義非共軛轉置
flipdim
以指定維交換對稱位置上的元素
ipermute
廣義反轉置,permute的反操作
shiftdim
維移動函數
【例2-33】 多維數組元素對稱交換函數flipdim使用示例。
>> A=reshape(1:18,2,3,3) % 創建演示三維數組
A(:,:,1) =
1 3 5
2 4 6
A(:,:,2) =
7 9 11
8 10 12
A(:,:,3) =
13 15 17
14 16 18
>> B=flipdim(A,1) % 以第1維進行對稱變換
B(:,:,1) =
2 4 6
1 3 5
B(:,:,2) =
8 10 12
7 9 11
B(:,:,3) =
14 16 18
13 15 17
>> C=flipdim(A,3) % 以第3維進行對稱變換
C(:,:,1) =
13 15 17
14 16 18
C(:,:,2) =
7 9 11
8 10 12
C(:,:,3) =
1 3 5
2 4 6
從本例可以看出,函數flipdim(A,k)中的輸入變量k就是指進行對稱變換的維。另外flipdim(A,k)函數也可用於二維數組,讀者可以自行驗證。
【例2-34】 多維數組元素維移動函數shiftdim使用示例。
本例在上例所建立的三維數組A上進行演示。
>> D=shiftdim(A,1) % 將各維向左移動1位,使2*3*3數組變成3*3*2數組
D(:,:,1) =
1 7 13
3 9 15
5 11 17
D(:,:,2) =
2 8 14
4 10 16
6 12 18
>> E=shiftdim(A,2) % 將各維向左移動2位,使2*3*3數組變成3*2*3數組
E(:,:,1) =
1 2
7 8
13 14
E(:,:,2) =
3 4
9 10
15 16
E(:,:,3) =
5 6
11 12
17 18
運算D=shiftdim(A,1)實現以下操作:D(j,k,i)=A(i,j,k),i, j, k分別是指各維的下標。對於三維數組,D=shiftdim(A,3)的操作就等同於簡單的D=A。
【例2-35】 多維數組元素廣義非共軛函數permute使用示例。
本例在上例所建立的三維數組A上進行演示。
>> F=permute(A,[3 2 1])
F(:,:,1) =
1 3 5
7 9 11
13 15 17
F(:,:,2) =
2 4 6
8 10 12
14 16 18
>> G=permute(A,[3 1 2])
G(:,:,1) =
1 2
7 8
13 14
G(:,:,2) =
3 4
9 10
15 16
G(:,:,3) =
5 6
11 12
17 18
運算F=permute(A, [3 2 1])實現以下操作:F(k,j,i)=A(i,j,k),i, j, k分別是指各維的下標。函數permute就是函數shiftdim的特殊形式,它可以任意指定維的移動順序。