Pome资料库
Pome 切换暗/亮/自动模式 切换暗/亮/自动模式 切换暗/亮/自动模式 返回首页

多维矩阵转一维矩阵

说明

有的时候,为了运算方便或资料储存的空间问题,使用一维阵列会比二维或多维阵列来得方便,例如上三角矩阵、下三角矩阵或对角矩阵,使用一维阵列会比使用二维阵列来得节省空间。

解法

以二维阵列转一维阵列为例,索引值由0开始,在由二维阵列转一维阵列时,我们有两种方式:「以列(Row)为主」或「以行(Column)为主」。由于 C/C++、Java等的记忆体配置方式都是以列为主,所以您可能会比较熟悉前者(Fortran的记忆体配置方式是以行为主)。

以列为主的二维阵列要转为一维阵列时,是将二维阵列由上往下一列一列读入一维阵列,此时索引的对应公式如下所示,其中row与column是二维阵列索引,loc表示对应的一维阵列索引:

loc = column + row*行数

以行为主的二维阵列要转为一维阵列时,是将二维阵列由左往右一行一行读入一维阵列,此时索引的对应公式如下所示:

loc = row + column*列数

公式的推导您画图看看就知道了,如果是三维阵列,则公式如下所示,其中i(个数u1)、j(个数u2)、k(个数u3)分别表示三维阵列的三个索引:

以列为主:loc = iu2u3 + j*u3 + k

以行为主:loc = ku1u2 + j*u1 + i

更高维度的可以自行依此类推,但通常更高维度的建议使用其它资料结构(例如物件包装)会比较具体,也不易搞错。

在C/C++中若使用到指标时,会遇到指标运算与记忆体空间位址的处理问题,此时也是用到这边的公式,不过必须在每一个项上乘上资料型态的内存大小。

参考代码

C

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h> 
#include <stdlib.h> 

int main(void) { 
    int arr1[3][4] = {{1, 2, 3, 4}, 
                     {5, 6, 7, 8}, 
                     {9, 10, 11, 12}}; 
    int arr2[12] = {0}; 
    int row, column, i; 

    printf("原二维资料:\n"); 
    for(row = 0; row < 3; row++) { 
        for(column = 0; column < 4; column++) { 
            printf("%4d", arr1[row][column]); 
        } 
        printf("\n"); 
    } 

    printf("\n以列为主:"); 
    for(row = 0; row < 3; row++) { 
        for(column = 0; column < 4; column++) { 
            i = column + row * 4; 
            arr2[i] = arr1[row][column]; 
        } 
    } 
    for(i = 0; i < 12; i++) 
        printf("%d ", arr2[i]); 

    printf("\n以行为主:"); 
    for(row = 0; row < 3; row++) { 
        for(column = 0; column < 4; column++) { 
            i = row + column * 3; 
            arr2[i] = arr1[row][column]; 
        } 
    } 
    for(i = 0; i < 12; i++) 
        printf("%d ", arr2[i]); 

    printf("\n"); 

    return 0; 
}

Java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TwoDimArray {
    public static int[] toOneDimByRow(int[][] array) {
        int[] arr = new int[array.length * array[0].length];
        for(int row = 0; row < array.length; row++) { 
            for(int column = 0; 
                       column < array[0].length; column++) { 
                int i = column + row * array[0].length; 
                arr[i] = array[row][column]; 
            } 
        }
        return arr;
    }
    
    public static int[] toOneDimByColumn(int[][] array) {
        int[] arr = new int[array.length * array[0].length];
        for(int row = 0; row < array.length; row++) { 
            for(int column = 0; 
                        column < array[0].length; column++) { 
                int i = i = row + column * array.length;
                arr[i] = array[row][column]; 
            } 
        }
        return arr;
    }
}