使用分而治之的方法的矩阵乘法

时间:2016-01-25 13:58:36

标签: c recursion matrix-multiplication divide-and-conquer

我是编程初学者,刚刚学习了新概念并开始编写矩阵乘法代码,但我对指针和其他人感到困惑所以我在这里上传代码以寻求指导。

#include <stdio.h>
#include <stdlib.h>

int **matrixMultiply(int A[][8], int B[][8], int row);

int main() {
    int **A = allocate_matrix(A, 8, 8);
    int **B = allocate_matrix(B, 8, 8);

    int i, j;
    for (i = 0; i < 8; i++) {
        for (j = 0; j < 8; j++) {
            A[i][j] = i + j;
            A[i][j] = i + j;
        }
    }

    int **C = allocate_matrix(C, 8, 8);
    C = matrixMultiply(A, B, 8);

    return 0;
}

int **matrixMultiply(int A[][8], int B[][8], int row) {
    int **C = allocate_matrix(C, row, row);
    if (row == 1) {
        C[1][1] = A[1][1] * B[1][1];
    } else {
        int a11[row/2][row/2], a12[row/2][row/2], a21[row/2][row/2], a22[row/2][row/2];
        int b11[row/2][row/2], b12[row/2][row/2], b21[row/2][row/2], b22[row/2][row/2];
        int **c11 = allocate_matrix(c11, row/2, row/2);
        int **c12 = allocate_matrix(c12, row/2, row/2);
        int **c21 = allocate_matrix(c21, row/2, row/2);
        int **c22 = allocate_matrix(c22, row/2, row/2);

        int i, j;
        for (i = 0; i < row/2; i++) {
            for (j = 0; j < row/2; j++) {
                a11[i][j] = A[i][j];
                a12[i][j] = A[i][j + (row/2)];
                a21[i][j] = A[i + (row/2)][j];
                a22[i][j] = A[i + (row/2)][j + (row/2)];
                b11[i][j] = B[i][j];
                b12[i][j] = B[i][j + (row/2)];
                b21[i][j] = B[i + (row/2)][j];
                b22[i][j] = B[i + (row/2)][j + (row/2)];
                c11[i][j] = C[i][j];
                c12[i][j] = C[i][j + (row/2)];
                c21[i][j] = C[i + (row/2)][j];
                c22[i][j] = C[i + (row/2)][j + (row/2)];
            }
        }

        c11 = addmatrix(matrixMultiply(a11, b11, row/2),
                        matrixMultiply(a12, b21, row/2), c11, row/2);
        c12 = addmatrix(matrixMultiply(a11, b12, row/2),
                        matrixMultiply(a22, b22, row/2), c12, row/2);
        c21 = addmatrix(matrixMultiply(a21, b11, row/2),
                        matrixMultiply(a22, b21, row/2), c21, row/2);
        c22 = addmatrix(matrixMultiply(a21, b12, row/2),
                        matrixMultiply(a22, b22, row/2), c22, row/2);

        // missing code???
        return C;
    }
}

int **allocate_matrix(int **matrix, int row, int column) {
    matrix = (int **)malloc(row * sizeof(int*));
    int i;
    for (i = 0; i < row; i++) {
        matrix[row] = (int *)malloc(row * sizeof(int));
    }
    return matrix;
}

void deallocate_matrix(int **matrix, int row) {
    int i;
    for (i = 0; i < row; i++) {
        free(matrix[row]);
    }
    free(matrix);
}

int **addMatrix(int **a, int **b, int **c, int row) {
    int i, j;
    for (i = 0; i < row; i++) {
        for (j = 0; j < row; j++) {
            c[i][j] = a[i][j] + b[i][j];
        }
    }
    return c;
}

1 个答案:

答案 0 :(得分:1)

我重新格式化了您的代码,以便我可以对其进行分析。一致地缩进4个空格,在二元运算符周围插入空格,在,;分隔符之后以及在关键字和(之间插入空格,这大大提高了可读性。

matrixMultiply函数中似乎缺少代码:您分配了生成的矩阵C,但您将其用作初始化中间矩阵的输入c11,{{1} },c21c21,除了琐碎的1x1案例外,永远不会将任何内容存储到c22中。

矩阵乘法代码似乎超出此范围,该函数采用类型为C的2个参数,但是您使用定义为{{1}的本地数组int A[][8], int B[][8]a11递归调用它}。这些类型不同,我不知道代码是如何编译的。

在矩阵分配代码中,您分配的行大小不正确b22而不是int a11[row/2][row/2]。您应该使用row,因此矩阵初始化为column,而且您根本不应该传递初始参数:

calloc

第二个子矩阵乘法也有错误,应该是

0

此外,您永远不会释放用于中间结果的临时矩阵。与java不同,C没有垃圾收集器,当你不再需要它们时,你负责释放内存块,然后它们才会变得无法访问。

这是一个更正版本,具有打印矩阵数据和验证矩阵乘法正确性的额外功能。我添加了时间:递归方法比直接方法慢,主要是因为中间结果的所有额外分配/释放。

int **allocate_matrix(int row, int column) {
    int **matrix = malloc(row * sizeof(*matrix));
    for (int i = 0; i < row; i++) {
        matrix[i] = calloc(column, sizeof(*matrix[row]));
    }
    return matrix;
}