有效地存储三角矩阵

我需要通过不将所有零存储在内存中来有效地存储下三角矩阵,所以我已经考虑过这种方式:首先我为每一行分配内存,然后为每一行分配i + 1个字节,所以我永远不会不得不担心零,但在第一次分配时出现问题。 我究竟做错了什么? 这是我的代码,编译器在读取矩阵的维度后,在第8行退出程序。

#include  #include  int main () { int i, j, **mat1, dim; scanf("%d",&dim); *mat1 = (int**)calloc(dim, sizeof(int*)); for(i = 0; i<dim; i++) mat1[i] = (int*)calloc(i+1, sizeof(int)); for(i = 0; i < dim; i++) for(j = 0; j < i+1; j++) scanf("%d", &mat1[i][j]); for(i=0; i<dim; i++) for(j=0; j<(i+1); j++) printf("%d%c", mat1[i][j], j != (dim-1) ? ' ' : '\n'); return 0; } 

编辑

好吧,所以在你按照你帮助我的方式修改代码后,我必须阅读一个上三角形和一个下三角矩阵并显示它们的产品。这个问题是我没有将零存储在内存中,所以如果我使用传统的3-for算法,它会显示一些垃圾值。如果我用0初始化每个矩阵的其余部分,动态分配内存是没用的,因为我也会存储零,所以我没有做任何改进存储的效率。我想我必须在某处修改代码,或者可能是间隔,但无论如何我修改程序仍然输出(对于3×3矩阵)右上角的2个垃圾值。我怎么能这样做?

 #include  #include  int main () { int i,j,k,**mat1,**mat2,**prod,dim; printf("Give dimension: \n"); scanf("%d",&dim); mat1 = (int**)calloc(dim,sizeof(int*)); for(i=0; i-1; i--) mat2[i]=(int*)calloc(i+1,sizeof(int)); prod = (int**)calloc(dim,sizeof(int*)); for(i=0; i<dim; i++) prod[i] = (int*)calloc(dim,sizeof(int)); printf("Give lower triangular matrix(non 0 values only): \n"); for(i=0; i<dim; i++) for(j=0; j<i+1; j++) scanf("%d",&mat1[i][j]); printf("Give upper triangular matrix(non 0 values): \n"); for(i=0; i<dim; i++) for(j=i; j<dim;j++) scanf("%d",&mat2[i][j]); printf("Matrix A is: \n"); for(i=0; i<dim; i++) for(j=0; j<dim; j++) printf("%d%c",j<=i?mat1[i][j]:0,j!=dim-1?' ':'\n'); printf("Matrix B is: \n"); for(i=0; i<dim; i++) for(j=0; j=i?mat2[i][j]:0,j!=dim-1?' ':'\n'); for(i=0; i<dim; i++) for(j=0; j<dim; j++) for(k=0; k<dim; k++) prod[i][j]+=mat1[i][k]*mat2[k][j]; printf("The product of the two matrix is: \n"); for(i=0; i<dim; i++) for(j=0; j<dim; j++) printf("%d%c",prod[i][j],j!=dim-1?' ':'\n'); return 0; 

}

 mat1 = calloc(dim,sizeof(int*)); 

mat1是一个双指针。你需要为你的指针数组分配内存,然后你需要单独为每个指针分配内存。不需要强制转换calloc()

如果您想节省空间和分配矩阵的每一行的开销,您可以通过使用单个数组的巧妙索引来实现三角矩阵。

下三角矩阵(包括对角线)具有以下属性:

 尺寸矩阵元素/行总元素
 1 x。  。  。  1 1
 2 xx。  。  2 3
 3 xxx。  3 6
 4 xxxx 4 10
 ...

给定维度的元素总数为:

 size(d) = 1 + 2 + 3 + ... + d = (d+1)(d/2) 

如果在一个数组中连续排列行,则可以使用上面的公式计算矩阵内给定行和列(均为零)的偏移量:

 index(r,c) = size(r-1) + c 

上面的公式用于下三角矩阵。 您可以通过简单地反转索引来访问上部矩阵,就好像它是一个较低的矩阵:

 index((d-1)-r, (d-1)-c) 

如果您担心更改数组的方向,可以为上部数组设计不同的偏移计算,例如:

 uindex(r,c) = size(d)-size(dr) + cr 

示例代码:

 #include  #include  #include  #define TRM_SIZE(dim) (((dim)*(dim+1))/2) #define TRM_OFFSET(r,c) (TRM_SIZE((r)-1)+(c)) #define TRM_INDEX(m,r,c) ((r)<(c) ? 0 : (m)[TRM_OFFSET((r),(c))]) #define TRM_UINDEX(m,r,c,d) ((r)>(c)?0:(m)[TRM_SIZE(d)-TRM_SIZE((d)-(r))+(c)-(r)]) #define UMACRO 0 int main (void) { int i, j, k, dimension; int *ml, *mu, *mr; printf ("Enter dimension: "); if (!scanf ("%2d", &dimension)) { return 1; } ml = calloc (TRM_SIZE(dimension), sizeof *ml); mu = calloc (TRM_SIZE(dimension), sizeof *mu); mr = calloc (dimension*dimension, sizeof *mr); if (!ml || !mu || !mr) { free (ml); free (mu); free (mr); return 2; } /* Initialization */ srand (time (0)); for (i = 0; i < TRM_SIZE(dimension); i++) { ml[i] = 100.0*rand() / RAND_MAX; mu[i] = 100.0*rand() / RAND_MAX; } /* Multiplication */ for (i = 0; i < dimension; i++) { for (j = 0; j < dimension; j++) { for (k = 0; k < dimension; k++) { mr[i*dimension + j] += #if UMACRO TRM_INDEX(ml, i, k) * TRM_UINDEX(mu, k, j, dimension); #else TRM_INDEX(ml, i, k) * TRM_INDEX(mu, dimension-1-k, dimension-1-j); #endif } } } /* Output */ puts ("Lower array"); for (i = 0; i < dimension; i++) { for (j = 0; j < dimension; j++) { printf (" %2d", TRM_INDEX(ml, i, j)); } putchar ('\n'); } puts ("Upper array"); for (i = 0; i < dimension; i++) { for (j = 0; j < dimension; j++) { #if UMACRO printf (" %2d", TRM_UINDEX(mu, i, j, dimension)); #else printf (" %2d", TRM_INDEX(mu, dimension-1-i, dimension-1-j)); #endif } putchar ('\n'); } puts ("Result"); for (i = 0; i < dimension; i++) { for (j = 0; j < dimension; j++) { printf (" %5d", mr[i*dimension + j]); } putchar ('\n'); } free (mu); free (ml); free (mr); return 0; } 

请注意,这是一个简单的例子。 您可以扩展它以将矩阵指针包装在一个结构中,该结构还存储矩阵的类型(上下三角形或正方形)和尺寸,以及根据矩阵类型适当操作的写访问函数。

对于任何非平凡的矩阵使用,您应该使用专门研究矩阵的第三方库。

您在第8行取消引用mat1 ,然后将其设置为指向任何位置。 你正在为int分配一个指针数组,但你没有将它分配给mat1,而是指向mat1的解引用,这是未初始化的,我们不知道它指向的是什么。

所以这一行:

 // ERROR: You are saying an unknown memory location should have the value of calloc. *mat1 = (int**)calloc(dim,sizeof(int*)); 

应改为:

 // OK: Now you are assigning the allocation to the pointer variable. mat1 = (int**)calloc(dim,sizeof(int*));