어떻게 메모리에 삼각형 행렬을 효율적으로 저장합니까?

문제의 세부 사항

메모리에 0을 모두 저장하지 않고 lower triangular matrix을 저장하고 싶습니다.
내가 그것을 실현하는 방식은 제i + 1i원소에 공간을 분배하는 것이다.
그러나 나는 C 언어의 동적 메모리 분배에 대해 아직 익숙하지 않아서, 나의 첫 분배에 문제가 있는 것 같다.
int main ()
{
    int i, j;
    int **mat1;
    int 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]);
        }
    }

    /* Print the matrix without the zeros*/
    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;
}

저에게 가장 유용한 답안입니다.

공간과 분배 행렬의 각 줄의 비용을 절약하고 싶다면 단일 수조에 대한 교묘한 인덱스를 통해 삼각형 행렬을 실현할 수 있다.
대각선을 포함한 아래 삼각형 행렬에는 다음과 같은 특성이 있습니다.
Dimension   Matrix    Elements/row   Total elements
1           x . . .   1              1
2           x x . .   2              3
3           x x x .   3              6
4           x x x x   4              10
...

The total number of elements for a given dimension is:

size(d) = 1 + 2 + 3 + ... + d  =  (d+1)(d/2)
단일 배열에서 행을 연속으로 배열하는 경우 위의 방정식 계산 행렬에서 지정된 행과 열(0을 기준으로 함)의 오프셋을 사용할 수 있습니다.
index(r,c) = size(r-1) + c
상기 공식은 하삼각 행렬에 적용된다.인덱스를 간단히 반전하여 아래 매트릭스에 액세스하는 것처럼 위 매트릭스에 액세스할 수 있습니다.
index((d-1)-r, (d-1)-c)
패턴의 방향을 변경할 염려가 있는 경우 위쪽 패턴에 대해 다음과 같은 다른 오프셋 계산을 설계할 수 있습니다.
uindex(r,c) = size(d)-size(d-r) + c-r
코드 예:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

#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;
}
이것은 보잘것없는 예이니 주의해 주십시오.매트릭스 포인터를 구조에 봉하여 매트릭스의 유형(상삼각형 또는 하삼각형 또는 정사각형)과 크기를 저장하고 매트릭스의 유형에 따라 적절한 조작 접근 함수를 작성할 수 있도록 확장할 수 있습니다.
행렬의 어떠한 평범하지 않은 사용에 대해서도 행렬을 전문적으로 연구하는 제3자 라이브러리를 사용해야 할 수 있습니다.