2015-01-17 2 views
0

두 개의 희소 행렬 (A와 B)을 만든 다음 세 번째 희소 행렬 (C)에 추가하는 과제가 있습니다. 나는 이미 벡터 (두 개의 희소 벡터를 받고 세 번째 벡터에 추가)를 사용하여 작업을 마쳤으므로 일련의 벡터를 사용하여 매트릭스를 표현하는 것이 더 쉬울 것이라고 결정했습니다. 앞으로 벡터없이 벡터화 할 필요가 있습니다. 실제 행렬을 사용해야 할 수도 있습니다. (심지어는 희소 행렬에 숫자를 삽입하는 함수의 가짜 코드가 있습니다.) 그래서 이해하십시오 나는 다음 코드 다소이 작동하더라도이.C에서 연결된 목록을 사용하여 스파 스 행렬 만들기

행렬이므로 행 배열 및 열 배열 인 포인터의 두 배열 이 있습니다. 배열의 각 셀은 해당 행/열을 가리 킵니다. 그것은 아래의 그림과 같이이다 :

the numbers represent {row,column,data

은 제로가 스파 스 매트릭스가, 당신이 존재하지 않는 그들과 함께 제로가 그 노드로 그 화살표가 표시된다.

문제를 단순화하기 위해 이미지에서 볼 수 있듯이 각 행의 헤드를 가리키는 행 배열 만 처리하는 것이 좋습니다. 각 행을 벡터 C로 가정합니다 (위에서 말한 것처럼 일련의 벡터로 행렬을 나타내려고합니다).

List *Create_vector (List *A, List *B, int i, int m) 
{ 
    int l,flag = 0; 
    List *C; 
    List_node *node=NULL, *next, *Pointer_A, *Pointer_B; 
    C = create_list(); 
    Pointer_A = A->head; 
    Pointer_B = B->head; 

    for (l = 0; l<m; l++) 
    { 
     if ((Pointer_A->key + Pointer_B->key) != 0) 
     { 
      if (flag == 0) 
      { 
       node = mk_node(Pointer_A->key + Pointer_B->key, i,l); 
       insert_first(node, C); 
       flag = 1; 
      } 
      else 
      { 
       next = mk_node(Pointer_A->key + Pointer_B->key, i,l); 
       insert(next, node); 
       node = next; 
      } 
     } 
     Pointer_A = Pointer_A->next; 
     Pointer_B = Pointer_B->next; 
    } 
    return C; 
} 

그리고이 주요 프로그램 :

이 벡터를 생성하는 코드가

typedef struct List_node 
{ 
    int key; 
    int i,j; 
    struct List_node *next; 
}List_node; 

typedef struct List 
{ 
    List_node *head; 
}List; 

List *create_list() 
{ 
    List *list = (List*)malloc(sizeof(List)); 
    list->head = NULL; 
    return list; 
} 

void insert_first(List_node *x, List *list) 
{ 
    x->next = list->head; 
    list->head = x; 
} 

void insert(List_node *x, List_node *y) 
{ 
    x->next = y->next; 
    y->next = x; 
} 

List_node *mk_node(int data, int row, int col) 
{ 
    List_node *node = (List_node *)malloc(sizeof(List_node)); 
    node->key = data; 
    node->i = row + 1; 
    node->j = col + 1; 
    return node; 
} 

void delete_list(List *list) 
{ 
    List_node *node, *temp; 
    node = list->head; 
    while (node != NULL) 
    { 
     temp = node->next; 
     free(node); 
     node = temp; 
    } 
    free(list); 
} 

void print_list(List *list, char name) 
{ 
    List_node *p; 
    p = list->head; 
    printf("\nThe linked list %c consists of: ",name); 
    while (p != NULL) 
    { 
     printf("%d(i = %d) (j = %d) ", p->key, p->i, p->j); 
     p = p->next; 
    } 
    printf("\n"); 
} 

:

은 내가 만든 링크 된 목록의 모든 기능의 코드
void main() 
{ 
    List_node *Row_A, *Row_B, *Row_C; 

    List *A, *B, *C; 
    List_node *node, *next; 
    int data, m,n,l; 
    printf("Enter list row\n"); 
    scanf("%d", &m); 

    Row_A = (List_node*)malloc(sizeof(int)*(m)); 
    Row_B = (List_node*)malloc(sizeof(int)*(m)); 
    Row_C = (List_node*)malloc(sizeof(int)*(m)); 

    printf("Enter list columns\n"); 
    scanf("%d", &n); 

    for (int i=0; i<m; i++) 
    { 

     A = create_list(); 
     B = create_list(); 

     printf("\nInsert first number into A\n"); 
     scanf("%d", &data); 
     node = mk_node(data, i,0); 
     insert_first(node, A); 
     for (l = 1; l<n; l++) 
     { 
      printf("Now insert the rest of the numbers\n"); 
      scanf("%d", &data); 
      next = mk_node(data, i,l); 
      insert(next, node); 
      node = next; 
     } 
     print_list(A,'A'); 

     printf("\nInsert first number into B\n"); 
     scanf("%d", &data); 
     node = mk_node(data,i,0); 
     insert_first(node, B); 
     for (l = 1; l<n; l++) 
     { 
      printf("Now insert the rest of the numbers\n"); 
      scanf("%d", &data); 
      next = mk_node(data, i,l); 
      insert(next, node); 
      node = next; 
     } 
     print_list(B,'B'); 

     C = Create_vector(A,B,i,n); 
    } 
    getchar(); getchar(); 
} 

바라 건데 당신이 이걸 가지고 있기를 바랍니다. 그래서 내 문제는 다음과 같습니다.

  1. 내가 필요한 포인터의 배열 Row_A, Row_B, Row_C를 만드는 방법을 모르겠습니다. 의미, 각 셀이 벡터의 머리를 가리키고 있다면 어떻게 배열을 정의 할 수 있습니까? 목록으로? 목록 노드? 배열의 모든 셀을 각 벡터의 머리를 가리 키도록하려면 어떻게해야합니까?

  2. 목록 C는 for 루프가 실행될 때마다 재정의됩니다. 각 벡터 C를 유지하고 행렬에 넣을 수있는 유일한 방법은 각 벡터가 각 벡터의 머리를 가리 키도록하는 것입니다. 그러면 문제 # 1로 되돌아갑니다. 그게 사실이야? 어떻게해야합니까?

대단히 감사합니다. 당신이 시작할 수 있습니다

답변

2

일부 관찰 :

  • 당신은 당신이 당신의 동적 배열 Row_A 등을 만들 다만 방법을 헤드의 목록을 만들 수 있습니다. 이러한 헤드 목록은 독립형 데이터 구조가 아니어야합니다. 이 List 구조체의 일부인 것처럼 Matrix 구조체의 일부 여야합니다. 헤드 배열의 할당은 생성자 함수 create_matrix의 일부 여야합니다.

  • 헤드의 각 Matrix 저장 자신의 목록도 C을 덮어 쓰기의 해결책이 사실 대신 C->head[i]에 할당, 반복 C에 할당 할. 마찬가지로 AB에 대해서도 마찬가지입니다. 행렬을 설명하는 모든 날짜는 하나의 구조체에 캡슐화되어야 모든 것이 깔끔하게 저장됩니다.

  • 현재 매트릭스를 행 목록으로 나타냅니다. 인쇄 및 행렬 추가에는 문제가 없지만 일단 곱셈을하면 열 머리가 필요합니다. 그런 다음 노드 구조는 스케치에서 설명한대로 두 개의 포인터를 갖도록 준비해야합니다. 행의 다음 요소 (right)에 대한 포인터와 열의 다음 요소에 대한 포인터 (below).

  • 매트릭스가 희박하지 않습니다. 예를 들어, 두 개의 목록 (create_vector이라고해서는 안되는 것을 추가해야 함)을 추가하는 코드는 노드와 연관된 색인을 검사하여 0 항목을 건너 뛸 수 있도록해야합니다.

  • 구조체에 목록 또는 행렬의 크기를 저장해야합니다. 이는 목록을 탐색하는 데 필요하지 않지만 작업이 합법적인지 여부를 신속하게 확인할 수 있습니다. 예를 들어 같은 차원의 행렬 만 추가 할 수 있습니다. 예를 들어

:

typedef struct Matrix Matrix; 
typedef struct Matrixnode Matrixnode; 

struct Matrix { 
    int n, m; 
    Matrixnode *row; 
    Matrixnode *col; 
}; 

Matrix *create_matrix(int n, int m) 
{ 
    Matrix *mx = malloc(sizeof(*mx)); 

    mx->n = n; 
    mx->m = m; 

    mx->row = malloc(m * sizeof(*m->row)); 
    mx->col = malloc(n * sizeof(*n->col)); 

    return mx; 
} 

Matrix *matrix_add(const Matrix *a, const Matrix *b) 
{ 
    assert(a->m == b->m); 
    assert(a->n == b->n); 

    Matrix *c = create_matrix(a->n, a->m); 

    for (int i = 0; i < c->m; i++) { 
     c->row[i] = row_add(a->row[i], b->row[i]); 
    } 

    return c; 
} 

이 당신이 행 벡터의 배열을 만들 수있는 방법의 대략적인 스케치입니다. (나는 col 배열을 만들었지 만 그것을 사용하지 않는다. 행렬을 추가 할 때, 일관되게 컬럼 포인터를 유지해야한다.)

+0

고맙습니다. 첫 번째와 두 번째 관찰에 대해 자세히 설명해 주시겠습니까? 샘플 코드에서 의미하는 바를 보여 주시겠습니까? 그게 니가 의미하는 바를 잘 모르겠다 니 정말 도움이 될거야. 또한, 네 번째 관찰에 대해서,'create_vector' 함수에서'if ((Pointer_A-> key + Pointer_B-> key)! = 0)'행은 0 항목을 건너 뛰게됩니다. – Eran

+0

답변을 업데이트했습니다. –