如何在C中转置矩阵? - 错误
How to transpose a matrix in C? - error
我正在尝试编写一个函数来转置矩阵。
该函数的参数:
要转置的矩阵
输出矩阵为空。
问题是我能够转置一些矩阵,但其他一些矩阵失败了,就像我在示例中给出的那样。为什么?我该如何解决?
代码:
int main (void)
{
//this works well
/* double array[3][2] = {{1,2},{3,4},{5,6}};
height = 3;
width = 2;
*/
//this input doesn't work
double array[2][3] = {{1,2,3},{4,5,6}};
height = 2;
width = 3;
int heightOutput = width; //2
int widthOutput = height; //3
double **output;
output = malloc(widthOutput * sizeof(double *)); //rows from 1
for (i = 0; i < widthOutput; i++)
{
output[i] = malloc(heightOutput * sizeof(double)); //columns
}
transposeMatrix(&array[0][0], height,width, &output[0][0], heightOutput, widthOutput);
printf("\n");
printf("\noutput matrix\n");
for(i=0;i<heightOutput;i++)
{
for(j=0;j<widthOutput;j++)
{
printf("%f\t",output[i][j]);
}
printf("\n");
}
}
void transposeMatrix(double* array2, int height, int width, double * output, int height2, int width2)
{
double workaround[3][3] ={0};
double result;
int i,j;
printf("input matrix:\n");
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
printf("%f\t",(*((array2+i*width)+j)));
}
printf("\n");
}
printf("\n");
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
result = (*((array2+i*width)+j));
workaround[i][j] = result;
}
}
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
*((output+j*3)+i) = workaround[i][j];
printf("%f\t",(*((output+j*3)+i)));
}
printf("\n");
}
}
主要问题是您混淆了矩阵的大小。
当你填充 workaround
矩阵时你的循环应该是这样的,因为原始矩阵的大小是 (height
x width
).
for(i=0;i<width;i++)
{
for(j=0;j<height;j++)
{
result = (*((array2+i*width)+j));
workaround[i][j] = result;
}
}
转置矩阵时
for(i=0;i<height2;i++)
{
for(j=0;j<width2;j++)
{
*((output+i*width2)+j) = workaround[j][i];
printf("%f\t",(*((output+i*width2)+j)));
}
}
在内存分配中你也得到了错误的大小,应该是
output = malloc(heightOutput * sizeof(double *)); //rows from 1
for (i = 0; i < heightOutput; i++)
{
output[i] = malloc(widthOutput * sizeof(double)); //columns
}
通过此更改,您的程序将 运行 没有错误,但输出仍然是错误的
input matrix:
1.000000 2.000000 3.000000
4.000000 5.000000 6.000000
1.000000 2.000000 3.000000
4.000000 5.000000 6.000000
output matrix
1.000000 4.000000
5.000000 0.000000
0.000000 0.000000
最后一个问题是参数传递。您动态分配内存,首先指向行的指针
output = malloc(heightOutput * sizeof(double *)); //rows from 1
这样你就得到了指针数组
* -> NULL
* -> NULL
* -> NULL
并使用循环为它们赋值
for (i = 0; i < heightOutput; i++)
{
output[i] = malloc(widthOutput * sizeof(double)); //columns
}
* -> [e00, e01]
* -> [e10, e11]
* -> [e20, e21]
但是不能保证它们会一个接一个地分配,您仍然可以像线性分配数据一样使用 output
进行操作。要正确使用它,您需要传递双指针。
void transposeMatrix(double* array2, int height, int width, double ** output, int height2, int width2)
{
...
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
output[j][i] = workaround[i][j];
printf("%f\t",output[j][i]);
}
printf("\n");
}
}
如果你想分配内存线性做如下
output = malloc(heightOutput * widthOutput * sizeof(double));
但对我来说这一切看起来有点复杂,简单来说就是
void transposeMatrix(double* src, double* dst, int n, int m)
{
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < m; ++j)
dst[j * n + i] = src[i * m + j];
}
int main(void)
{
double array[2][3] = {{1,2,3},{4,5,6}};
int height = 2;
int width = 3;
int i, j;
double *output = malloc(height * width * sizeof(double));
printf("input matrix\n");
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
printf("%f\t",array[i][j]);
}
printf("\n");
}
transposeMatrix(&array[0][0], output, height,width);
printf("output matrix\n");
for(i=0;i<width;i++)
{
for(j=0;j<height;j++)
{
printf("%f\t",output[i*height + j]);
}
printf("\n");
}
}
编辑:
回答您的评论:假设我们有矩阵 4 * 5
| a00 a01 a02 a03 a04 |
| a10 a11 a12 a13 a14 |
| a20 a21 a22 a23 a24 |
| a30 a31 a32 a33 a34 |
在分配给
的内存中
// n = 4, m = 5
double* A = malloc(n * m * sizeof(double));
看起来像
| a00 a01 a02 a03 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24 a30 a31 a32 a33 a34 |
所以要获取元素,比如说 (2, 3),我们需要跳过 2 * 5 个元素(每行有 5 个元素)和从第三行开始的 3 个元素,所以 - 要跳过的 13 个元素在数组中。
为了对矩阵 m * n 进行泛化以获得 (i, j) 元素,我们需要跳过数组中的 (i * m) + j 元素。
include stdio.h
include conio.h
include string.h
include stdlib.h
int main(){
int i,j,n,t=0,a[100][100],k,l,b=0;
printf(" n="); // you write the number or rows and columns or the matrix
scanf("%d",&n);
for(i=1;i<=n;i++){ //you write the elements of the matrix
for(j=1;j<=n;j++){
printf("a[%d][%d]=",i,j);
scanf("%d",&a[i][j]);
}
}
printf("\n");
for(i=1;i<=n;i++){ //you can see you original matrix
for(j=1;j<=n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("\n -\n");
for (i=2; i<=n; i++) { //now we transpose the original matrix
for (j=1; j < i; j++) {
t = a[i][j];
a[i][j] = a[j][i];
a[j][i] = t;
printf("\n da \n");
}
}
// 现在我们可以看到矩阵的转置
// 并将其与第一个进行比较
printf("\n \n ");
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("\n \n");
system("PAUSE");
return 0;
我正在尝试编写一个函数来转置矩阵。
该函数的参数:
要转置的矩阵
输出矩阵为空。
问题是我能够转置一些矩阵,但其他一些矩阵失败了,就像我在示例中给出的那样。为什么?我该如何解决?
代码:
int main (void)
{
//this works well
/* double array[3][2] = {{1,2},{3,4},{5,6}};
height = 3;
width = 2;
*/
//this input doesn't work
double array[2][3] = {{1,2,3},{4,5,6}};
height = 2;
width = 3;
int heightOutput = width; //2
int widthOutput = height; //3
double **output;
output = malloc(widthOutput * sizeof(double *)); //rows from 1
for (i = 0; i < widthOutput; i++)
{
output[i] = malloc(heightOutput * sizeof(double)); //columns
}
transposeMatrix(&array[0][0], height,width, &output[0][0], heightOutput, widthOutput);
printf("\n");
printf("\noutput matrix\n");
for(i=0;i<heightOutput;i++)
{
for(j=0;j<widthOutput;j++)
{
printf("%f\t",output[i][j]);
}
printf("\n");
}
}
void transposeMatrix(double* array2, int height, int width, double * output, int height2, int width2)
{
double workaround[3][3] ={0};
double result;
int i,j;
printf("input matrix:\n");
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
printf("%f\t",(*((array2+i*width)+j)));
}
printf("\n");
}
printf("\n");
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
result = (*((array2+i*width)+j));
workaround[i][j] = result;
}
}
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
*((output+j*3)+i) = workaround[i][j];
printf("%f\t",(*((output+j*3)+i)));
}
printf("\n");
}
}
主要问题是您混淆了矩阵的大小。
当你填充
workaround
矩阵时你的循环应该是这样的,因为原始矩阵的大小是 (height
xwidth
).for(i=0;i<width;i++) { for(j=0;j<height;j++) { result = (*((array2+i*width)+j)); workaround[i][j] = result; } }
转置矩阵时
for(i=0;i<height2;i++) { for(j=0;j<width2;j++) { *((output+i*width2)+j) = workaround[j][i]; printf("%f\t",(*((output+i*width2)+j))); } }
在内存分配中你也得到了错误的大小,应该是
output = malloc(heightOutput * sizeof(double *)); //rows from 1 for (i = 0; i < heightOutput; i++) { output[i] = malloc(widthOutput * sizeof(double)); //columns }
通过此更改,您的程序将 运行 没有错误,但输出仍然是错误的
input matrix: 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 1.000000 2.000000 3.000000 4.000000 5.000000 6.000000 output matrix 1.000000 4.000000 5.000000 0.000000 0.000000 0.000000
最后一个问题是参数传递。您动态分配内存,首先指向行的指针
output = malloc(heightOutput * sizeof(double *)); //rows from 1
这样你就得到了指针数组
* -> NULL * -> NULL * -> NULL
并使用循环为它们赋值
for (i = 0; i < heightOutput; i++) { output[i] = malloc(widthOutput * sizeof(double)); //columns } * -> [e00, e01] * -> [e10, e11] * -> [e20, e21]
但是不能保证它们会一个接一个地分配,您仍然可以像线性分配数据一样使用
output
进行操作。要正确使用它,您需要传递双指针。void transposeMatrix(double* array2, int height, int width, double ** output, int height2, int width2) { ... for(i=0;i<width2;i++) { for(j=0;j<height2;j++) { output[j][i] = workaround[i][j]; printf("%f\t",output[j][i]); } printf("\n"); } }
如果你想分配内存线性做如下
output = malloc(heightOutput * widthOutput * sizeof(double));
但对我来说这一切看起来有点复杂,简单来说就是
void transposeMatrix(double* src, double* dst, int n, int m)
{
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < m; ++j)
dst[j * n + i] = src[i * m + j];
}
int main(void)
{
double array[2][3] = {{1,2,3},{4,5,6}};
int height = 2;
int width = 3;
int i, j;
double *output = malloc(height * width * sizeof(double));
printf("input matrix\n");
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
printf("%f\t",array[i][j]);
}
printf("\n");
}
transposeMatrix(&array[0][0], output, height,width);
printf("output matrix\n");
for(i=0;i<width;i++)
{
for(j=0;j<height;j++)
{
printf("%f\t",output[i*height + j]);
}
printf("\n");
}
}
编辑: 回答您的评论:假设我们有矩阵 4 * 5
| a00 a01 a02 a03 a04 |
| a10 a11 a12 a13 a14 |
| a20 a21 a22 a23 a24 |
| a30 a31 a32 a33 a34 |
在分配给
的内存中// n = 4, m = 5
double* A = malloc(n * m * sizeof(double));
看起来像
| a00 a01 a02 a03 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24 a30 a31 a32 a33 a34 |
所以要获取元素,比如说 (2, 3),我们需要跳过 2 * 5 个元素(每行有 5 个元素)和从第三行开始的 3 个元素,所以 - 要跳过的 13 个元素在数组中。 为了对矩阵 m * n 进行泛化以获得 (i, j) 元素,我们需要跳过数组中的 (i * m) + j 元素。
include stdio.h
include conio.h
include string.h
include stdlib.h
int main(){
int i,j,n,t=0,a[100][100],k,l,b=0;
printf(" n="); // you write the number or rows and columns or the matrix
scanf("%d",&n);
for(i=1;i<=n;i++){ //you write the elements of the matrix
for(j=1;j<=n;j++){
printf("a[%d][%d]=",i,j);
scanf("%d",&a[i][j]);
}
}
printf("\n");
for(i=1;i<=n;i++){ //you can see you original matrix
for(j=1;j<=n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("\n -\n");
for (i=2; i<=n; i++) { //now we transpose the original matrix
for (j=1; j < i; j++) {
t = a[i][j];
a[i][j] = a[j][i];
a[j][i] = t;
printf("\n da \n");
}
}
// 现在我们可以看到矩阵的转置
// 并将其与第一个进行比较
printf("\n \n ");
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
printf("\n \n");
system("PAUSE");
return 0;