Невозможно создать матрицу связанного списка - PullRequest
1 голос
/ 25 апреля 2020

Я пытаюсь преобразовать массив в матрицу связанного списка. Если я введу:

1 2 3
4 5 6
7 8 9

, то матрица связанного списка будет примерно такой:

1 -> 2 -> 3 -> NULL
|    |    |
v    v    v
4 -> 5 -> 6 -> NULL
|    |    |
v    v    v
7 -> 8 -> 9 -> NULL
|    |    |
v    v    v
NULL NULL NULL

Я попытался отладить код. Я получаю ошибку ошибки сегментации в col = col->down. Но я не могу понять причину этой ошибки. Вот код для вашей справки.

#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
  int data;
  struct node *next;
  struct node *down;
}matrix;
matrix *start = NULL;
void insert();
void arrToMatrix();
void arrDisplay();
void matrixDisplay();
int a[10][10];
int r,c;
int main()
{
  int n;
  printf("1:Insert elements 2:Convert Array to Linked Matrix 3:Display Array 4:Display Linked Matrix\n");
 for(;;)
 {
   printf("Enter choice: ");
   scanf("%d",&n);
   switch(n)
   {
      case 1: insert();
      break;
      case 2: arrToMatrix();
      break;
      case 3: arrDisplay();
      break;
      case 4: matrixDisplay();
      break;
      default: printf("Wrong Input\n");
      exit(0);
   }
 }
 return 0;
}

void insert()
{
  int i,j;
  printf("Enter row: ");
  scanf("%d",&r);
  printf("\nEnter column: ");
  scanf("%d",&c);
  printf("Enter elements: \n");
  for(i=0;i<r;i++)
      for(j=0;j<c;j++)
        scanf("%d",&a[i][j]);
}
void arrDisplay()
{
  int i,j;
  printf("Array elements: \n");
  for(i=0;i<r;i++)
  {
    for(j=0;j<c;j++)
    {
      printf("%d ",a[i][j]);
    }
    printf("\n");
  }
}
void arrToMatrix()
{
  int i,j;
  matrix *ptr, *col, *row;
  ptr = malloc(sizeof(matrix));
  ptr->data = a[0][0];
  ptr->next = NULL;
  ptr->down = NULL;
  start = ptr;
  col = start;
  for(i=0;i<r;i++)
  {
    row = col;
    for(j=0;j<c;j++)
    {
      ptr = malloc(sizeof(matrix));
      ptr->data = a[i][j];
      ptr->next = NULL;
      ptr->down = NULL;
      if(row == col)
        row = ptr;
      else
      {
        while(row->next!=NULL)
          row = row->next;
        row->next = ptr;
      }
    }
    col = col->down;
  }
}

void matrixDisplay()
{
  matrix *row, *col, *ptr;
  col = start;
  while(col!=NULL)
  {
    row = col;
    while(row!=NULL)
    {
      printf("%d ",row->data);
      row = row->next;
    }
    printf("\n");
    col = col->down;
  }
}

Ответы [ 3 ]

1 голос
/ 25 апреля 2020

Хорошее упражнение. У меня есть решение, использующее подход матрицы c указателей. Вы можете распределить его динамически таким же образом, но только для того, чтобы получить представление.

Итак, здесь мы go:

#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
  int data;
  struct node *next;
  struct node *down;
} matrix;

matrix *start = NULL;

#define MAX_DIM 10

matrix ptrMatrix[MAX_DIM][MAX_DIM];

void insert();
void arrToMatrix();
void arrDisplay();
void matrixDisplay();

int a[MAX_DIM][MAX_DIM];
int r,c;

int main()
{
  int n;
 for(;;)
 {
   printf("1:Insert elements 2:Convert Array to Linked Matrix 3:Display Array 4:Display Linked Matrix\n");
   printf("Enter choice: ");
   scanf("%d",&n);
   switch(n)
   {
      case 1: insert();
      break;
      case 2: arrToMatrix();
      break;
      case 3: arrDisplay();
      break;
      case 4: matrixDisplay();
      break;
      default: printf("Wrong Input\n");
      exit(0);
   }
 }
 return 0;
}

void insert()
{
  int i,j;
  printf("Enter number of rows: ");
  scanf("%d",&r);
  printf("\nEnter number of columns: ");
  scanf("%d",&c);

  if(r >= MAX_DIM)
  {
      printf("\nNo more than %d rows please!\n");
      return;
  }

  if(c >= MAX_DIM)
  {
      printf("\nNo more than %d columns please!\n");
      return;
  }

  printf("\n Now enter the elements (%d number in total): \n", r*c);
  for(i=0;i<r;i++)
  {
      for(j=0;j<c;j++)
      {
        scanf("%d",&a[i][j]);
      }
  }
}
void arrDisplay()
{
  int i,j;
  printf("Array elements: \n");
  for(i=0;i<r;i++)
  {
    for(j=0;j<c;j++)
    {
      printf("%d ",a[i][j]);
    }
    printf("\n");
  }
}
void arrToMatrix()
{
  if(r<=0 || c <=0)
  {
      printf("Matrix is empty. Try again!\n");
      return;
  }

  int i,j;

  for(i=0;i<r-1;i++)
  {
      for(j=0;j<c-1;j++)
      {
        ptrMatrix[i][j].data = a[i][j];
        ptrMatrix[i][j].next = &ptrMatrix[i][j+1];
        ptrMatrix[i][j].down = &ptrMatrix[i+1][j];
      }

      ptrMatrix[i][c-1].data = a[i][c-1];
      ptrMatrix[i][c-1].next = NULL;
      ptrMatrix[i][c-1].down = &ptrMatrix[i+1][c-1];
  }

  for(j=0;j<c-1;j++)
  {
    ptrMatrix[r-1][j].data = a[r-1][j];
    ptrMatrix[r-1][j].next = &ptrMatrix[r-1][j+1];
    ptrMatrix[r-1][j].down = NULL;
  }

  ptrMatrix[r-1][c-1].data = a[r-1][c-1];
  ptrMatrix[r-1][c-1].next = NULL;
  ptrMatrix[r-1][c-1].down = NULL;

  start = &(ptrMatrix[0][0]);
}

void matrixDisplay()
{
  matrix *row, *col;
  col = start;
  while(col!=NULL)
  {
    row = col;
    while(row!=NULL)
    {
      printf("%d ",row->data);
      row = row->next;
    }
    printf("\n");
    col = col->down;
  }
}
0 голосов
/ 25 апреля 2020

Назначение не является простым для новичка.

Для начинающих это плохая идея, когда используются глобальные переменные, такие как start, а определения функций зависят от глобальных переменных.

Например, Вы не можете определить в своей программе более одной матрицы.

Внутри функции arrToMatrix вам приходится иметь дело с указателями на указатели. В противном случае функция будет более сложной или запуск указателя не изменится, поскольку изменение локальных переменных col и row в вашей программе не влияет на i = на начало указателя. И, кроме того, например, в этом фрагменте кода

  ptr = malloc(sizeof(matrix));
  ptr->data = a[i][j];
  ptr->next = NULL;
  ptr->down = NULL;
  if(row == col)
    row = ptr;

имеется избыточное распределение узла, когда i равно 0, а j равно 0.

В начале функции текущая матрица, указанная указателем головы, должна быть освобождена. В противном случае возможны утечки памяти, и пользователь не сможет переназначить матрицу с другим массивом.

Поэтому вам нужно написать еще одну функцию, которая освобождает всю выделенную память для текущей матрицы.

Вот демонстрационная программа, которая показывает, как функции могут быть реализованы. В программе есть закомментированная функция matrixDisplay, используемая для тестирования. Вы можете запустить его вместо функции без комментариев matrixDisplay, чтобы увидеть, как определяется список и его ссылки.

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
    int data;
    struct node *next;
    struct node *down;
} matrix;

void deleteMatrix( matrix **head )
{
    if ( *head != NULL )
    {
        for ( matrix *row = ( *head )->next; row != NULL; )
        {
            while ( row != NULL )
            {
                matrix *tmp = row;
                row = row->next;
                free( tmp );
            }

            row = ( *head )->down;

            if ( ( *head )->down != NULL )
            {
                ( *head )->down = row->down;
            }
        }

        free( *head );
        *head = NULL;
    }
}

void arrToMatrix( matrix **head, size_t m, size_t n, int a[m][n] )
{
    deleteMatrix( head );

    matrix **row = head;

    for ( size_t i = 0; i < m; i++ )
    {
        matrix **column = row;

        for ( size_t j = 0; j < n; j++ )
        {
            *column = malloc( sizeof( matrix ) );
            ( *column )->data = a[i][j];
            ( *column )->down = NULL;
            ( *column )->next = NULL;

            column = &( *column )->next;    
        }

        row = &( *row )->down;
    }

    row = head;

    for ( size_t i = 0; i + 1 < m; i++ )
    {
        matrix *column   = *row;
        matrix *next_row_column = ( *row )->down;

        for ( size_t j = 0; j < n; j++ )
        {
            column->down = next_row_column;
            column = column->next;
            next_row_column = next_row_column->next;
        }           

        row = &( *row )->down;
    }
}

void matrixDisplay( const matrix *head )
{
    for ( ; head != NULL; head = head->down )
    {
        for ( const matrix *column = head; column != NULL; column = column->next )
        {
            printf( "%2d ", column->data );
        }
        putchar( '\n' );
    }
}
/*
void matrixDisplay( const matrix *head )
{
    for ( ; head != NULL; head = head->down )
    {
        for ( const matrix *column = head; column != NULL; column = column->next )
        {
            printf( "%2d ( %p ): next( %p ), down( %p )  ", 
                     column->data, ( void * )column, ( void * )column->next, ( void * )column->down );
        }
        putchar( '\n' );
    }
}
*/
int main(void) 
{
    enum { N = 3 };
    int a[][N] = 
    {
        { 1, 2, 3 },
        { 4, 5, 6 },
        { 7, 8, 9 }
    };

    matrix *head = NULL;

    arrToMatrix( &head, N, N, a );

    matrixDisplay( head );
    putchar( '\n' );

    deleteMatrix( &head );

    return 0;
}

Вывод программы:

 1  2  3 
 4  5  6 
 7  8  9 

Вывод прокомментированная функция matrixDisplay может выглядеть, например, следующим образом.

 1 ( 0x558b577e7260 ): next( 0x558b577e7280 ), down( 0x558b577e72c0 )   2 ( 0x558b577e7280 ): next( 0x558b577e72a0 ), down( 0x558b577e72e0 )   3 ( 0x558b577e72a0 ): next( (nil) ), down( 0x558b577e7300 )  
 4 ( 0x558b577e72c0 ): next( 0x558b577e72e0 ), down( 0x558b577e7320 )   5 ( 0x558b577e72e0 ): next( 0x558b577e7300 ), down( 0x558b577e7340 )   6 ( 0x558b577e7300 ): next( (nil) ), down( 0x558b577e7360 )  
 7 ( 0x558b577e7320 ): next( 0x558b577e7340 ), down( (nil) )   8 ( 0x558b577e7340 ): next( 0x558b577e7360 ), down( (nil) )   9 ( 0x558b577e7360 ): next( (nil) ), down( (nil) )  
0 голосов
/ 25 апреля 2020

ptr-> down всегда NULL в вашем случае. оно никогда не инициализируется. поэтому col = col-> down назначает значение NULL для col

...