【问题标题】:Matrix inside another matrix另一个矩阵内的矩阵
【发布时间】:2018-12-13 00:20:18
【问题描述】:

我应该使用什么方法来编写一个函数来检查一个矩阵是否包含在另一个矩阵中? 例如:

     matrix A           matrix B
  1   2.  3.  4   5      2  3
  6   7.   8.  9   10    7  8
  11  12. 13. 14  15     12 13
  16  17  18  19  20

我添加了点来指出矩阵 A 中的矩阵 B。

到目前为止我已经写了这个:

#include <stdio.h>

int matrica_sadrzana(int* m1, int v1, int s1, int* m2, int v2, int s2){

    /* What needs to go here? */
    return 0;
}

int main() {
    int i,j,v1,v2,s1,s2,sadrzana;
    int matricaA[100][100],matricaB[100][100];
    printf("Unesite visinu i sirinu matrice A: ");
    scanf("%d %d",&v1,&s1);
    printf("Unesite visinu i sirinu matrice B: ");
    scanf("%d %d",&v2,&s2);
    for(i=0; i<v1; i++){
        for(j=0; j<s1; j++){
            scanf("%d",&matricaA[i][j]);

        }
    }
    for(i=0; i<v2; i++){
        for(j=0; j<s2; j++){
            scanf("%d",&matricaB[i][j]);

        }
    }
    sadrzana=matrica_sadrzana(matricaA,v1,s1,matricaB,v2,s2);

    return 0;
}

【问题讨论】:

  • 应该将参数从int* m1 更改为int s1, int m1[][s1]。您可以通过这种方式指定第二个维度。
  • 我相信您的问题是如何找到一个数组/矩阵中的元素/整数是否包含在另一个数组/矩阵中?
  • 哦,有道理。但是检查矩阵元素的逻辑是什么,这才是真正困扰我的地方。你能给我一些提示吗?
  • 是的,这就是我要问的。不仅是一个,而是整个矩阵 B。一种确定矩阵 B 的元素是否以不改变矩阵 B 的顺序的顺序包含在矩阵 A 中的方法。
  • This answer 可能会鼓舞人心

标签: c arrays matrix


【解决方案1】:

您可以创建一个 findNum() 函数,该函数返回一个布尔值 true 或 false,并接受行大小、col 大小、二维数组(第二维由传入的 col 大小指定)和一个数字你想检查一下。因此,在您的情况下,您可以遍历 Matrix A,为 Matrix A 中的每个元素调用 findNum() 以检查 Matrix B 是否包含它。 findNum() 将在第一次遇到它正在检查的数字时返回 true。如果数字不在那里,那么它将返回 false。

例如:

_Bool findNum(int row, int col, int arr2d[][col], int chk) {
    for(int i = 0; i < row; ++i) {
        for(int j = 0; j < col; ++j) {
            if(arr2d[i][j] == chk)
                return 1;
        }
    }

    return 0;
}

使用它(这应该打印“匹配!”三次,因为 0 包含在 arr2d2 但 5 不是):

int arr2d1[2][2] = {0};
int arr2d2[2][3] = {0};

/* Change a value in arr2d1 so they're not identical */
arr2d1[0][0] = 5;

/* Element we're sending to findNum() */
int element = 0;

/* Traverse through arr2d1 */
for(int i = 0; i < 2; ++i) {
    for(int j = 0; j < 2; ++j) {
        element = arr2d1[i][j];
        /* Check if the current element is contained
         * in arr2d2; do whatever if so */
        if(findNum(2, 3, arr2d2, element)) {
            printf("Match!\n");
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以使用固定长度数组或可变长度数组来做到这一点。

    定长数组

    您从固定长度的数组开始,所以第一个程序跟随您的脚步。您必须在传递数组时指定数组的第二维——否则,代码将访问错误的数据。您的编译器应该一直在抱怨对您的函数的调用。我使用初始化数据而不是从标准输入中读取。输入代码被注释掉(并且未经测试)。

    #include <stdio.h>
    
    static int matrica_subset(int m1[][100], int r1, int c1, int m2[][100], int r2, int c2)
    {
        for (int m = 0; m < r2; m++)
        {
            for (int n = 0; n < c2; n++)
            {
                printf("ss: m1[%d][%d] = %d; m2[%d][%d] = %d\n", r1+m, c1+n, m1[r1+m][c1+n], m, n, m2[m][n]);
                if (m1[r1+m][c1+n] != m2[m][n])
                    return 0;
            }
        }
        return 1;
    }
    
    static int matrica_sadrzana(int m1[][100], int r1, int c1, int m2[][100], int r2, int c2)
    {
        if (c1 < c2 || r1 < r2)
            return 0;
        int c_max = c1 - c2 + 1;
        int r_max = r1 - r2 + 1;
        for (int r = 0; r < r_max; r++)
        {
            for (int c = 0; c < c_max; c++)
            {
                printf("sa: m1[%d][%d] = %d; m2[0][0] = %d\n", r, c, m1[r][c], m2[0][0]);
                if (m1[r][c] == m2[0][0])
                {
                    if (matrica_subset(m1, r, c, m2, r2, c2) != 0)
                    {
                        printf("match at m1[%d][%d]\n", r, c);
                        return 1;
                    }
                }
            }
        }
        return 0;
    }
    
    int main(void)
    {
        int sadrzana, c1 = 5, c2 = 2, r1 = 4, r2 = 3;
        int matricaA[100][100] =
        {
            {   1,   2,   3,   4,   5, },
            {   6,   7,   8,   9,  10, },
            {  11,  12,  13,  14,  15, },
            {  16,  17,  18,  19,  20, },
        };
        int matricaB[100][100] =
        {
            {   2,   3, },
            {   7,   8, },
            {  12,  13, },
        };
    
        //printf("rows and columns for matrix A: ");
        //scanf("%d %d", &r1, &c1);
        //printf("rows and columns for matrix B: ");
        //scanf("%d %d", &r2, &c2);
        //printf("data for matrix A:\n");
        //for (int i = 0; i < r1; i++)
        //{
        //    for (int j = 0; j < c1; j++)
        //    {
        //        scanf("%d", &matricaA[i][j]);
        //    }
        //}
        //printf("data for matrix B:\n");
        //for (int i = 0; i < r2; i++)
        //{
        //    for (int j = 0; j < c2; j++)
        //    {
        //        scanf("%d", &matricaB[i][j]);
        //    }
        //}
    
        sadrzana = matrica_sadrzana(matricaA, r1, c1, matricaB, r2, c2);
        printf("sadrzana: %d\n", sadrzana);
    
        return 0;
    }
    

    matrica_subset() 函数从 m1 行开始查找 r1c1 以匹配大小为 r2 活动行和 c2 活动列的 m2 main() 中定义的 100x100 矩阵。

    matrica_sadrzana() 协调搜索,检查m2 的左上角是否与m1 中的当前位置匹配,并在匹配时使用matrica_subset() 函数继续搜索。

    样本输出:

    sa: m1[0][0] = 1; m2[0][0] = 2
    sa: m1[0][1] = 2; m2[0][0] = 2
    ss: m1[0][1] = 2; m2[0][0] = 2
    ss: m1[0][2] = 3; m2[0][1] = 3
    ss: m1[1][1] = 7; m2[1][0] = 7
    ss: m1[1][2] = 8; m2[1][1] = 8
    ss: m1[2][1] = 12; m2[2][0] = 12
    ss: m1[2][2] = 19; m2[2][1] = 13
    sa: m1[0][2] = 3; m2[0][0] = 2
    sa: m1[0][3] = 4; m2[0][0] = 2
    sa: m1[1][0] = 6; m2[0][0] = 2
    sa: m1[1][1] = 7; m2[0][0] = 2
    sa: m1[1][2] = 8; m2[0][0] = 2
    sa: m1[1][3] = 9; m2[0][0] = 2
    sadrzana: 0
    

    变长数组

    使用可变长度数组的替代方法需要matrica_subset() 函数的额外参数来指定数组的实际大小(r1c1)以及数组中的搜索位置(r0 和@987654339 @)。

    #include <stdio.h>
    
    static void dump_matrix(const char *tag, int r, int c, int m[r][c])
    {
        printf("%s (%dx%d):\n", tag, r, c);
        for (int i = 0; i < r; i++)
        {
            for (int j = 0; j < c; j++)
                printf(" %3d", m[i][j]);
            putchar('\n');
        }
    }
    
    static int matrica_subset(int r1, int c1, int m1[r1][c1], int r0, int c0, int r2, int c2, int m2[r2][c2])
    {
        for (int m = 0; m < r2; m++)
        {
            for (int n = 0; n < c2; n++)
            {
                printf("ss: m1[%d][%d] = %d; m2[%d][%d] = %d\n", r0+m, c0+n, m1[r0+m][c0+n], m, n, m2[m][n]);
                if (m1[r0+m][c0+n] != m2[m][n])
                    return 0;
            }
        }
        return 1;
    }
    
    static int matrica_sadrzana(int r1, int c1, int m1[r1][c1], int r2, int c2, int m2[r2][c2])
    {
        if (c1 < c2 || r1 < r2)
            return 0;
        int c_max = c1 - c2 + 1;
        int r_max = r1 - r2 + 1;
        for (int r = 0; r < r_max; r++)
        {
            for (int c = 0; c < c_max; c++)
            {
                printf("sa: m1[%d][%d] = %d; m2[0][0] = %d\n", r, c, m1[r][c], m2[0][0]);
                if (m1[r][c] == m2[0][0])
                {
                    if (matrica_subset(r1, c1, m1, r, c, r2, c2, m2) != 0)
                    {
                        printf("match at m1[%d][%d]\n", r, c);
                        return 1;
                    }
                }
            }
        }
        return 0;
    }
    
    int main(void)
    {
        int sadrzana, c1 = 5, c2 = 2, r1 = 4, r2 = 3;
        int matricaA[4][5] =
        {
            {   1,   2,   3,   4,   5, },
            {   6,   7,   8,   9,  10, },
            {  11,  12,  13,  14,  15, },
            {  16,  17,  18,  19,  20, },
        };
        int matricaB[3][2] =
        {
            {   2,   3, },
            {   7,   8, },
            {  12,  13, },
        };
    
        //printf("rows and columns for matrix A: ");
        //scanf("%d %d", &r1, &c1);
        //printf("rows and columns for matrix B: ");
        //scanf("%d %d", &r2, &c2);
        //printf("data for matrix A:\n");
        //for (int i = 0; i < r1; i++)
        //{
        //    for (int j = 0; j < c1; j++)
        //    {
        //        scanf("%d", &matricaA[i][j]);
        //    }
        //}
        //printf("data for matrix B:\n");
        //for (int i = 0; i < r2; i++)
        //{
        //    for (int j = 0; j < c2; j++)
        //    {
        //        scanf("%d", &matricaB[i][j]);
        //    }
        //}
        dump_matrix("Matrix A", r1, c1, matricaA);
        dump_matrix("Matrix B", r2, c2, matricaB);
    
        sadrzana = matrica_sadrzana(r1, c1, matricaA, r2, c2, matricaB);
        printf("sadrzana: %d\n", sadrzana);
    
        return 0;
    }
    

    样本输出:

    Matrix A (4x5):
       1   2   3   4   5
       6   7   8   9  10
      11  12  13  14  15
      16  17  18  19  20
    Matrix B (3x2):
       2   3
       7   8
      12  13
    sa: m1[0][0] = 1; m2[0][0] = 2
    sa: m1[0][1] = 2; m2[0][0] = 2
    ss: m1[0][1] = 2; m2[0][0] = 2
    ss: m1[0][2] = 3; m2[0][1] = 3
    ss: m1[1][1] = 7; m2[1][0] = 7
    ss: m1[1][2] = 8; m2[1][1] = 8
    ss: m1[2][1] = 12; m2[2][0] = 12
    ss: m1[2][2] = 13; m2[2][1] = 13
    match at m1[0][1]
    sadrzana: 1
    

    惊喜,惊喜——它返回相同的结果。搜索功能适用于可变长度数组;数据仍然存储在固定大小的数组中(因为您不能对 VLA 使用初始化程序),但大小比原始代码中的要小得多。

    VLA 代码还会转储输入矩阵; FLA 代码没有。将转储代码添加到第一个程序中是相当容易的,但打印功能并不那么通用。可以安排转储 RxC 矩阵的 NxM 子段;这对代码来说有点繁琐,但非常通用,可以在两个程序中使用——但 VLA 程序会简单地设置 N 和 R 相等,M 和 C 相等。

    【讨论】:

    • 您好,非常感谢!但是我设法自己解决了它,它类似于您的“固定长度数组”解决方案,但我的是一个函数和四个嵌套循环,如果您有兴趣,我可以发送给您。感谢您的回答!
    • 我有一个有 4 个循环的版本,以及一个跳出最内层循环的 goto。那是我编写子集函数的时候。它有两个内部循环并使用 return 而不是 goto。由于它是静态的并且只调用一次,所以一个体面的编译器无论如何都会内联它
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多