将矩阵2D转换为1D

时间:2013-09-14 12:01:32

标签: c vector matrix

我有一个问题是将矩阵2D传递给带有C函数的向量(1D数组)。有我想要创建的代码:

#include <stdio.h>
#define N  64
#define A  8


int tab2[A][A];
int vect[N];
void fonc(int i,int j,int k,int l,int c,int **tab2,int *vect);

void fonc(int i,int j,int k,int l,int c,int **tab2,int *vect){

vect[k]=tab2[0][0];
printf("%d",vect[k]);
  while(i!=8 && j!=8)
    {
        //bas
        i=i;
    j=j+1;


    vect[k]++;
      printf("%d\t",vect[k]);
    //descente
    while(j !=0)
    {
     i=i+1;
     j=j-1;

     vect[k]++;
    }

    //droite
    i=i;
    j=j+1;

    vect[k]++;
     //montée
    while(i !=0)
    {
     i=i-1;
     j=j+1;

     vect[k]++;
    }
    }

}



int main (){
    int vect[64] ;
int tab2[8][8]={
{1, 2, 6, 7, 15, 16 ,28 ,1},
{3, 5, 8, 14, 17 ,27 ,29 ,1},
{4, 9, 13, 18, 26, 30, 39 ,1},
{10, 12, 19, 25, 31 ,38 ,40 ,1},
{11, 20 ,24, 32 ,37 ,41 ,46 ,1} ,
{21 ,23, 33, 36, 42, 45, 47 ,1},
{22, 34 ,35, 43, 44, 48, 49 ,1},
{22, 34 ,35, 43, 44, 48, 49 ,1}};
    int i;
    int j;
    int k;

fonc(i,j,k,8,8,tab2,vect);
//printf("%d\n", ) ;//limpide !
return 0;
}

我没有错误,但它调试我不能结果somoene有一个想法我该怎么办,我使用函数应用Zigzag线性变换为jpeg压缩RLE编码感谢所有人  我试着这样做: enter image description here

0, 0
0, 1    1, 0
2, 0    1, 1    0, 2
0, 3    1, 2    2, 1    3, 0
4, 0    3, 1    2, 2    1, 3    0, 4
0, 5    1, 4    2, 3    3, 2    4, 1    5, 0
6, 0    5, 1    4, 2    3, 3    2, 4    1, 5    0, 6
0, 7    1, 6    2, 5    3, 4    4, 3    5, 2    6, 1    7, 0
7, 1    6, 2    5, 3    4, 4    3, 5    2, 6    1, 7
2, 7    3, 6    4, 5    5, 4    6, 3    7, 2

3 个答案:

答案 0 :(得分:14)

您的函数有3个不必要的参数 - ijk。在main()中传递给函数的值未初始化;函数中ij中传递的值无关紧要,因为代码在首次使用时设置变量。使用k中的值,但传递给函数的值是不确定的。这需要改变,以便减少三个参数,它们只是函数中的局部变量,并且它们都需要设置为零。 (k是向量中的索引,其中应分配矩阵中的下一个值; ij是数组的下标。

你应该失去两个全局变量;它们永远不会被引用,因为main()中的局部变量会隐藏它们,而函数的参数会隐藏它们。从不使用这两个#define值。

虽然您传递了lc(行和列),但忽略它们并假设上限为l = 8c = 8。此外,您尝试传递给fonc的类型不是int **tab2;它是int tab2[][8]int tab2[8][8]。功能签名也可以成为:

void fonc(int tab2[8][8], int *vect);

在您的函数中,表单vect[k]++;的每个作业都应该是vect[k++] = tab2[i][j];形式的作业。

Zig-zag算法非常适合编码。对于8x8固定大小的矩阵,只需将索引序列打包到数组中即可。我假设之字形图的左上角是(0,0),右下角是(7,7)。如果这是错的,你只需修复表的初始化程序。

static const struct ZigZag
{
    unsigned char y, x;  // Reversed from original
} zigzag[] =
{
    { 0, 0 }, { 1, 0 }, { 0, 1 }, { 0, 2 },
    { 1, 1 }, { 2, 0 }, { 3, 0 }, { 2, 1 },
    { 1, 2 }, { 0, 3 }, { 0, 4 }, { 1, 3 },
    ...
    { 7, 5 }, { 7, 6 }, { 6, 7 }, { 7, 7 },
};

正确的复制操作很简单:

for (int i = 0; i < 64; i++)
    vect[i] = tab[zigzag[i].x][zigzag[i].y];

我们可以讨论写作64 vs sizeof(zigzag)/sizeof(zigzag[0])。如果你真的缺少内存(目前数据只有128个字节,所以我不相信你),那么你可以将这两个坐标打包成一个字节进行存储:

static const unsigned char zigzag[] =
{
    0x00, 0x10, 0x01, 0x02, ...
};

然后使用更复杂的下标表达式:

vect[i] = tab[zigzag[i] >> 4][zigzag[i] & 0xF];

由于内存访问量减少可能会更快 - 您必须进行测量。

这一切都假设您正在处理8x8固定大小的方阵。如果你必须处理任何大小的阵列并且仍然可以完成这项工作,那么你可能需要对事物进行编码,以便指定起点,向右走一步,沿对角线向左走,直到到达边缘(左边或你往前走一步或向右走,向右斜上去直到你到达边缘(顶部或右边),向右或向下走一步,然后重复直到你到达终点。整齐地编码很繁琐;复制循环不会是两行。

来自问题的检测代码

以下是问题中的代码,稍微清理了一下,但fonc()中的核心算法未更改 - 至少在处理ij和{{时保持不变1}}除了初始化它们。 main函数打印出之前的矩阵,以及调用k之后的向量。 <{1}}中对向量的每个分配都已修复并进行了检测。

fonc()

示例输出:

fonc()

请注意:

  1. 您访问超出范围的#include <stdio.h> void fonc(int tab2[8][8], int *vect); void fonc(int tab2[8][8], int *vect) { int i = 0; int j = 0; int k = 0; vect[k] = tab2[i][j]; printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]); while (i != 8 && j != 8) { // bas i = i; j = j+1; vect[k++] = tab2[i][j]; printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]); // descente while (j != 0) { i = i+1; j = j-1; vect[k++] = tab2[i][j]; printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]); } // droite i = i; j = j+1; vect[k++] = tab2[i][j]; printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]); // montée while (i != 0) { i = i-1; j = j+1; printf("v[%2d] = m[%2d][%2d] = %d\n", k, i, j, tab2[i][j]); vect[k++] = tab2[i][j]; } } } int main(void) { int vect[64]; int tab2[8][8] = { // Up to element value 28, the data should appear in // the order 1, 2, 3, ... in the output vector {1, 2, 6, 7, 15, 16, 28, 1}, {3, 5, 8, 14, 17, 27, 29, 1}, {4, 9, 13, 18, 26, 30, 39, 1}, {10, 12, 19, 25, 31, 38, 40, 1}, {11, 20, 24, 32, 37, 41, 46, 1}, {21, 23, 33, 36, 42, 45, 47, 1}, {22, 34, 35, 43, 44, 48, 49, 1}, {22, 34, 35, 43, 44, 48, 49, 1} }; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) printf("%3d", tab2[i][j]); putchar('\n'); } fonc(tab2, vect); for (int i = 0; i < 8 * 8; i++) { printf("%3d", vect[i]); if (i % 8 == 7) putchar('\n'); } return 0; }
  2. 当您的对角线移动到达矩阵的底部或右侧时,您的算法会遇到问题。
  3. 如果您没有C99和VLA支持,处理变量NxM阵列将会很痛苦。
  4. 表驱动程序

      1  2  6  7 15 16 28  1
      3  5  8 14 17 27 29  1
      4  9 13 18 26 30 39  1
     10 12 19 25 31 38 40  1
     11 20 24 32 37 41 46  1
     21 23 33 36 42 45 47  1
     22 34 35 43 44 48 49  1
     22 34 35 43 44 48 49  1
    v[ 0] = m[ 0][ 0] = 1
    v[ 1] = m[ 0][ 1] = 2
    v[ 2] = m[ 1][ 0] = 3
    v[ 3] = m[ 1][ 1] = 5
    v[ 3] = m[ 0][ 2] = 6
    v[ 5] = m[ 0][ 3] = 7
    v[ 6] = m[ 1][ 2] = 8
    v[ 7] = m[ 2][ 1] = 9
    v[ 8] = m[ 3][ 0] = 10
    v[ 9] = m[ 3][ 1] = 12
    v[ 9] = m[ 2][ 2] = 13
    v[10] = m[ 1][ 3] = 14
    v[11] = m[ 0][ 4] = 15
    v[13] = m[ 0][ 5] = 16
    v[14] = m[ 1][ 4] = 17
    v[15] = m[ 2][ 3] = 18
    v[16] = m[ 3][ 2] = 19
    v[17] = m[ 4][ 1] = 20
    v[18] = m[ 5][ 0] = 21
    v[19] = m[ 5][ 1] = 23
    v[19] = m[ 4][ 2] = 24
    v[20] = m[ 3][ 3] = 25
    v[21] = m[ 2][ 4] = 26
    v[22] = m[ 1][ 5] = 27
    v[23] = m[ 0][ 6] = 28
    v[25] = m[ 0][ 7] = 1
    v[26] = m[ 1][ 6] = 29
    v[27] = m[ 2][ 5] = 30
    v[28] = m[ 3][ 4] = 31
    v[29] = m[ 4][ 3] = 32
    v[30] = m[ 5][ 2] = 33
    v[31] = m[ 6][ 1] = 34
    v[32] = m[ 7][ 0] = 22
    v[33] = m[ 7][ 1] = 34
    v[33] = m[ 6][ 2] = 35
    v[34] = m[ 5][ 3] = 36
    v[35] = m[ 4][ 4] = 37
    v[36] = m[ 3][ 5] = 38
    v[37] = m[ 2][ 6] = 39
    v[38] = m[ 1][ 7] = 1
    v[39] = m[ 0][ 8] = 3
      2  3  5  6  7  8  9 10
     12 13 14 15 16 17 18 19
     20 21 23 24 25 26 27 28
      1 29 30 31 32 33 34 22
     34 35 36 37 38 39  1  3
      0  0  0  0  0  0  0  0
      0  0  0  0  0  0  0  0
      0  0  0  0  0  0  0  0
    

    示例输出:

    tab2[0][8]

    Anonymous

    的已修改代码版本

    Anonymous提供了answer。这在概念上非常有趣,但我不确定它是否准确。对它进行检测以便打印输入和输出并不是决定性因素,因此我将上面的代码放在同一个表中,该表应该产生向量1..64。代码和输出是:

    #include <stdio.h>
    
    void fonc(int tab2[8][8], int vect[8]);
    
    void fonc(int tab2[8][8], int vect[8])
    {
        static const struct ZigZag
        {
            unsigned char y, x;
        } zigzag[8*8] =
        {
            { 0, 0 }, { 1, 0 }, { 0, 1 }, { 0, 2 },
            { 1, 1 }, { 2, 0 }, { 3, 0 }, { 2, 1 },
            { 1, 2 }, { 0, 3 }, { 0, 4 }, { 1, 3 },
            { 2, 2 }, { 3, 1 }, { 4, 0 }, { 5, 0 },
            { 4, 1 }, { 3, 2 }, { 2, 3 }, { 1, 4 },
            { 0, 5 }, { 0, 6 }, { 1, 5 }, { 2, 4 },
            { 3, 3 }, { 4, 2 }, { 5, 1 }, { 6, 0 },
            { 7, 0 }, { 6, 1 }, { 5, 2 }, { 4, 3 },
            { 3, 4 }, { 2, 5 }, { 1, 6 }, { 0, 7 },
            { 1, 7 }, { 2, 6 }, { 3, 5 }, { 4, 4 },
            { 5, 3 }, { 6, 2 }, { 7, 1 }, { 7, 2 },
            { 6, 3 }, { 5, 4 }, { 4, 5 }, { 3, 6 },
            { 2, 7 }, { 3, 7 }, { 4, 6 }, { 5, 5 },
            { 6, 4 }, { 7, 3 }, { 7, 4 }, { 6, 5 },
            { 5, 6 }, { 4, 7 }, { 5, 7 }, { 6, 6 },
            { 7, 5 }, { 7, 6 }, { 6, 7 }, { 7, 7 },
        };
    
        for (int i = 0; i < 64; i++)
            vect[i] = tab2[zigzag[i].x][zigzag[i].y];
    }
    
    // The output vector should be in order 1..64
    int main(void)
    {
        int vect[64];
        int tab2[8][8] =
        {
            {  1,  2,  6,  7, 15, 16, 28, 29 },
            {  3,  5,  8, 14, 17, 27, 30, 43 },
            {  4,  9, 13, 18, 26, 31, 42, 44 },
            { 10, 12, 19, 25, 32, 41, 45, 54 },
            { 11, 20, 24, 33, 40, 46, 53, 55 },
            { 21, 23, 34, 39, 47, 52, 56, 61 },
            { 22, 35, 38, 48, 51, 57, 60, 62 },
            { 36, 37, 49, 50, 58, 59, 63, 64 }
        };
    
        puts("Matrix:");
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
                printf("%3d", tab2[i][j]);
            putchar('\n');
        }
    
        fonc(tab2, vect);
    
        puts("Vector:");
        for (int i = 0; i < 8 * 8; i++)
        {
            printf("%3d", vect[i]);
            if (i % 8 == 7)
                putchar('\n');
        }
    
        return 0;
    }
    

    输出:

    Matrix:
      1  2  6  7 15 16 28 29
      3  5  8 14 17 27 30 43
      4  9 13 18 26 31 42 44
     10 12 19 25 32 41 45 54
     11 20 24 33 40 46 53 55
     21 23 34 39 47 52 56 61
     22 35 38 48 51 57 60 62
     36 37 49 50 58 59 63 64
    Vector:
      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 43 44 45 46 47 48
     49 50 51 52 53 54 55 56
     57 58 59 60 61 62 63 64
    

    结果不太正确,但我确信这是正确的方向。 (同样清楚的是,这太复杂了,无法对Anonymous的问题发表评论 - 因此这里有这个补充。)

    从概念上讲,代码正在转动方形矩阵以使其站在其点上,然后在(8 + 8 - 1)条线上来回水平扫描。

    用于3x3扫描的ASCII艺术:

    #include <stdio.h>
    
    #define max(a, b) ((a) > (b) ? (a) : (b))
    #define min(a, b) ((a) > (b) ? (b) : (a))
    
    void dezigzag(int out[64], int in[8][8])
    {
        int n = 0;
        for (int diag = 0; diag < 15; diag++)
        {
            for (int i = max(0, diag - 7); i <= min(7, diag); i++)
                out[n++] = diag % 2 ? in[diag - i][i] : in[i][diag - i];
        }
    }
    
    int main(void)
    {
        int out[64] = {-1};
        int in[8][8];
    
        for (int i = 0; i < 64; i++)
            in[i % 8][i / 8] = i;
    
        puts("Matrix:");
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
                printf("%3d", in[i][j]);
            putchar('\n');
        }
    
        dezigzag(out, in);
    
        puts("Vector:");
        for (int i = 0; i < 8 * 8; i++)
        {
            printf("%3d", out[i]);
            if (i % 8 == 7)
                putchar('\n');
        }
    
        //for (int i = 0; i < 64; i++) {
        //    printf("%d: %d\n", i, out[i]);
        //}
    
        int tab2[8][8] =
        {
            {  1,  2,  6,  7, 15, 16, 28, 29 },
            {  3,  5,  8, 14, 17, 27, 30, 43 },
            {  4,  9, 13, 18, 26, 31, 42, 44 },
            { 10, 12, 19, 25, 32, 41, 45, 54 },
            { 11, 20, 24, 33, 40, 46, 53, 55 },
            { 21, 23, 34, 39, 47, 52, 56, 61 },
            { 22, 35, 38, 48, 51, 57, 60, 62 },
            { 36, 37, 49, 50, 58, 59, 63, 64 },
        };
    
        puts("Matrix:");
        for (int i = 0; i < 8; i++)
        {
            for (int j = 0; j < 8; j++)
                printf("%3d", tab2[i][j]);
            putchar('\n');
        }
    
        dezigzag(out, tab2);
    
        puts("Vector:");
        for (int i = 0; i < 8 * 8; i++)
        {
            printf("%3d", out[i]);
            if (i % 8 == 7)
                putchar('\n');
        }
    
        return 0;
    }
    

    有(3 + 3 - 1)= 5个扫描行。在表驱动代码中,与此对应的数据有规律性。

    修复匿名代码

    在函数Matrix: 0 8 16 24 32 40 48 56 1 9 17 25 33 41 49 57 2 10 18 26 34 42 50 58 3 11 19 27 35 43 51 59 4 12 20 28 36 44 52 60 5 13 21 29 37 45 53 61 6 14 22 30 38 46 54 62 7 15 23 31 39 47 55 63 Vector: 0 1 8 16 9 2 3 10 17 24 32 25 18 11 4 5 12 19 26 33 40 48 41 34 27 20 13 6 7 14 21 28 35 42 49 56 57 50 43 36 29 22 15 23 30 37 44 51 58 59 52 45 38 31 39 46 53 60 61 54 47 55 62 63 Matrix: 1 2 6 7 15 16 28 29 3 5 8 14 17 27 30 43 4 9 13 18 26 31 42 44 10 12 19 25 32 41 45 54 11 20 24 33 40 46 53 55 21 23 34 39 47 52 56 61 22 35 38 48 51 57 60 62 36 37 49 50 58 59 63 64 Vector: 1 3 2 6 5 4 10 9 8 7 15 14 13 12 11 21 20 19 18 17 16 28 27 26 25 24 23 22 36 35 34 33 32 31 30 29 43 42 41 40 39 38 37 49 48 47 46 45 44 54 53 52 51 50 58 57 56 55 61 60 59 63 62 64 中,赋值行需要反转条件。现有代码相当于:

       /\
      /\/\
     /\/\/\
     \/\/\/
      \/\/
       \/
    

    正确的代码是:

    dezigzag()

    然后输出:

    out[n++] = (diag % 2 == 1) ? in[diag - i][i] : in[i][diag - i];
    

    处理MxN阵列的代码

    out[n++] = (diag % 2 == 0) ? in[diag - i][i] : in[i][diag - i];
    

    使用迭代器结构的代码

    迭代器结构相当复杂。使用多个单行内联函数是极端的,但避免重复表达式。我确定有清理空间,但现在是时候停止玩乐了。

    Matrix:
      0  8 16 24 32 40 48 56
      1  9 17 25 33 41 49 57
      2 10 18 26 34 42 50 58
      3 11 19 27 35 43 51 59
      4 12 20 28 36 44 52 60
      5 13 21 29 37 45 53 61
      6 14 22 30 38 46 54 62
      7 15 23 31 39 47 55 63
    Vector:
      0  8  1  2  9 16 24 17
     10  3  4 11 18 25 32 40
     33 26 19 12  5  6 13 20
     27 34 41 48 56 49 42 35
     28 21 14  7 15 22 29 36
     43 50 57 58 51 44 37 30
     23 31 38 45 52 59 60 53
     46 39 47 54 61 62 55 63
    Matrix:
      1  2  6  7 15 16 28 29
      3  5  8 14 17 27 30 43
      4  9 13 18 26 31 42 44
     10 12 19 25 32 41 45 54
     11 20 24 33 40 46 53 55
     21 23 34 39 47 52 56 61
     22 35 38 48 51 57 60 62
     36 37 49 50 58 59 63 64
    Vector:
      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 43 44 45 46 47 48
     49 50 51 52 53 54 55 56
     57 58 59 60 61 62 63 64
    

答案 1 :(得分:7)

这是你用17次减少线条的方式:

#define N 8

int mat2d[N][N] = { /* stuff */ };
int vec1d[N * N];
memcpy(vec1d, mat2d, sizeof vec1d);

答案 2 :(得分:1)

每次迭代正方形的对角线,交替方向。

这是一个完整的,有效的例子(在c99中)。

#include <stdio.h>

#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))

void dezigzag(int out[64], int in[8][8]) {
    int n = 0;
    for (int diag = 0; diag < 15; diag++) {
        for (int i = max(0, diag - 7); i <= min(7, diag); i++) {
            out[n++] = diag % 2 ? in[diag - i][i] : in[i][diag - i];
        }
    }
}

int main(int argc, char *argv[]) {
    int out[64] = {-1};
    int in[8][8];
    for (int i = 0; i < 64; i++) {
        in[i % 8][i / 8] = i;
    }
    dezigzag(out, in);
    for (int i = 0; i < 64; i++) {
        printf("%d: %d\n", i, out[i]);
    }
    return 0;
}