Excepción StackOverflow operando подставляет матрицы

Он actualizado ми código siguiendo las pautas puntualizadas por las respuestas. La excepción StackOverflow никакой se ха vuelto producir, ya que no сушит сено recursividad бесконечный. Эмбарго греха, vuelvo подросток ООН problema: cuando le doy una matriz de orden 8 никаких devuelve la suma de los elementos de LA MATRIZ. Основной Y es que modifiqué el código para ello en la función, ya que la función equisuma lo que devuelve es la suma de los elementos de la submatriz equisuma. El enunciado del problema especifica que la matriz que se le da es cuadrada y de N potencia de 2, así que no сушит сено que elaborar el código teniendo en cuenta que la matriz puede никакой сер cuadrada o de N potencia distinta 2.

Ми Aquí adjunto código actualizado. Muchas gracias por губернатор испанской провинции:

#include <stdio.h>
typedef int MatrizEntero[10][10];


void main( ) {
int ancho;
int resultado;
printf("Deme el ancho de la matriz");
scanf("%d", &ancho);
resultado=equisuma( 0, 0, ancho );
if(ancho>2){
  if(resultado!=-1){
      resultado=resultado*ancho;


  printf("El resultado es %d", resultado);
  }
  else{
      printf("El resultado es %d", resultado);
     }


    }
  if(ancho==2){
  printf("El resultado es %d", resultado);

   }
   }



   int equisuma( int x, int y, int n ) {

   MatrizEntero m={{1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}};

   int res = 0;
   int sub = 0; //submatriz
   int subSize = 0;//tamaño de submatriz

   if( n == 2 ) {
// Suma de los cuatro elementos
   res = m[x][y] +
         m[x+1][y] +
         m[x][y+1] +
         m[x+1][y+1];

    } else {
// Tamaño de las submatrices
subSize = n / 2;

res = equisuma( x, y, subSize );

if( res != -1 ) {
  sub = equisuma( x + subSize, y, subSize );
  if( ( sub == -1 ) || ( sub != res ) )
    res = -1;
}

if( res != -1 ) {
  sub = equisuma( x, y + subSize, subSize );
  if( ( sub == -1 ) || ( sub != res ) )
    res = -1;
}

if( res != -1 ) {
  sub = equisuma( x + subSize, y + subSize, subSize );
  if( ( sub == -1 ) || ( sub != res ) )
    res = -1;
}
   }

   return res;
   }
3
задан 13.11.2016, 20:07
3 ответа

Я предлагаю тебе это другое планирование, которое использует возврат.

Параметры функции:
x, и: положение, внутри Даты, верхнего левого угла субмассива, который нужно считать.
size: ширина субмассива, которую нужно считать. Мы предполагаем, что она квадратная.

int Data[][]; /* Matriz general, principal, o como se quiera decir. */

int equisuma( int x, int y, int size ) {
  int result = 0;
  int sub = 0;
  int subSize = 0;

  if( size == 2 ) {
    /* Devolvemos la suma de los 4 elementos. */
    result = Data[x][y] +
             Data[x+1][y] +
             Data[x][y+1] +
             Data[x+1][y+1];
  } else {
    /* Tamaño de las submatrices. */
    subSize = size / 2;

    result = equisuma( x, y, subSize );

    if( result != -1 ) {
      sub = equisuma( x + subSize, y, subSize );
      if( ( sub == -1 ) || ( sub != result ) )
        result = -1;
    }

    if( result != -1 ) {
      sub = equisuma( x, y + subSize, subSize );
      if( ( sub == -1 ) || ( sub != result ) )
        result = -1;
    }

    if( result != -1 ) {
      sub = equisuma( x + subSize, y + subSize, subSize );
      if( ( sub == -1 ) || ( sub != result ) )
        result = -1;
    }
  }

  return result;
}

void main( ) {
  equisuma( 0, 0, AnchoDeLaMatriz );
}

Поскольку ты будешь видеть, используй классическую схему 'дели и ты победишь', и я думаю, что он приспосабливается к изложению. Ты будешь должен налаживать это в точные данные о твоей проблеме.

Я ИЗДАЮ

#include <stdio.h>

typedef int MatrizEntero[10][10];

int equisuma( int, int, int );

static MatrizEntero m = { { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 },
                          { 1, 1, 1, 1, 1, 1, 1, 1 } };

void main( ) {
  int ancho;
  int resultado;

  printf( "Deme el ancho de la matriz " );
  scanf( "%d", &ancho );

  resultado = equisuma( 0, 0, ancho );

  if( resultado == -1 ) {
    printf( "La matriz no es equisuma !!\n" );
  } else {
    printf( "El resultado es: %d\n", resultado );
  }
}

int equisuma( int x, int y, int ancho ) {
   int acumulado = 0;
   int subSuma = 0; //submatriz
   int subSize = 0;//tamaño de submatriz

   if( ancho == 2 ) {
    // La matriz tiene un ancho de 2.
    // Comprobamos si los 4 elementos son iguales.
    // Comparamos la esquina superior izquierda con los demás, para
    // aprovechar posibles cachés u optimizaciones del compilador.
    if( ( m[x][y] == m[x+1][y] ) &&
        ( m[x][y] == m[x][y+1] ) &&
        ( m[x][y] == m[x+1][y+1] ) ) {
      acumulado = m[x][y] +
                  m[x+1][y] +
                  m[x][y+1] +
                  m[x+1][y+1];
    } else {
      acumulado = -1;
    }
  } else {
    // Dividimos la matriz en 4 submatrices, y las vamos comprobando
    // secuencialmente.

    // Tamaño de las submatrices
    subSize = ancho / 2;

    // Esquina superior izquierda.
    // Al ser la primera llamada, no hay que comprobar nada.
    acumulado = equisuma( x, y, subSize );

    // Si era equisuma, comprobamos la esquina superior derecha.
    if( acumulado != -1 ) {
      subSuma = equisuma( x + subSize, y, subSize );
      acumulado = subSuma == -1 ? -1 : acumulado + subSuma;
    }

    // Esquina inferior izquierda.
    if( acumulado != -1 ) {
      subSuma = equisuma( x, y + subSize, subSize );
      acumulado = subSuma == -1 ? -1 : acumulado + subSuma;
    }

    // Esquina inferior derecha.
    if( acumulado != -1 ) {
      subSuma = equisuma( x + subSize, y + subSize, subSize );
      acumulado = subSuma == -1 ? -1 : acumulado + subSuma;
    }
  }
  return acumulado;
}

Измененный код разделяет recursivamente массив на субмассивы половины размера, до тех пор, пока они не 2x2. Если 4 стоимость этого массива 2x2 равна, он складывает их и возвращает результат. Если 4 стоимость не равна, возврати-1. Этот-1 возвращен во все так называемые предварительные переиталики.

Конечный результат - что только высшая стоимость, если все равны. Если какая-то стоимость отличная, покажи сообщение 'он не equisuma'.

Код прокомментирован щедро, будучи легким для того, чтобы быть измененным. 3 if концы внутри equisuma() они контролируют условия сумм, рядом с ? :

Последняя вещь. Размещать m = { . . . } внутри функции equisuma() это отклонение. Ты наполняешь батарейку с удвоенной полностью бесполезной информацией. Объявлять ее в начале файла, и соглашаться на нее - намного лучше (Это другое отклонение, если сам. Идеальное состояло бы в том, чтобы перемещать указатель в массив с данными в каждом вызове в equisuma(), но в этом конкретном случае он ничего не вносит; он больше, я думаю, что он затрудняет чтение и интерпретацию кода).

1
ответ дан 24.11.2019, 12:44
  • 1
    Не помещай два отличных ответов. В и # 241; ade новый пример в твой первоначальный ответ. У тебя есть bot и # 243; n " editar" я участвую в рыцарском турнире под той же самой. –  Francisco Romero 06.11.2016, 18:02
  • 2
    Ok. Новичок в сайте. В моем разряде, я был похож и # 243; достаточно различное как чтобы заслуживать отдельный ответ. Не возвращаться и # 225; чтобы происходить. –  Trauma 06.11.2016, 20:33
  • 3
    Much и # 237; пропасти спасибо за помощь. –  Montu 06.11.2016, 23:00
  • 4
    Большое спасибо из-за Вашего ответа. ¿ Он importarí чтобы говорить мне cuá l - funció n оператора?:? У меня нет большого количества опыта используя C, así что я не знаю того, что он делает. –  Montu 13.11.2016, 14:11
  • 5
    Я говорю это тебе, если ты расставляешь знаки препинания в ответе (ты даешь flechita для наверху) и acpetas (символ check). –  Trauma 13.11.2016, 17:13
int equisuma(MatrizEntero m, int nf, int nc){
  if(nf==2 && nc==2){
    // Calcula la suma
  }
  else{
    // Recursividad con nf/2 y nc/2
  }
}

Давайте представлять, что в функцию мы перемещаем его массив 6x6:

  • Поскольку это не массив 2x2, у нас есть возврат, nf/2=nc/2=3
  • Как продолжи, что, не будучи массивом 2x2, мы остаемся с возвратом. Сейчас nf/2=3/2=1
  • Останься, не будучи массивом 2x2... nf/2=1/2=0.
  • 0x0 продолжи, что, не будучи массивом 2x2..., он сейчас начинает развлекательное: 0/2=0. Предыдущее вычисление подразумевает, что функция будет входить в бесконечный возврат до тех пор, пока батарейка не перельется через край.

Если ты хочешь решить эту проблему с возвратом, ты должен иметь в виду, что размеры массива могут не быть делимыми между 2.

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

Другая проблема, которая у тебя есть, состоит в том, что твоя перекурсивная функция только получает число линий и колонн, но не показывает в какой линии / колонне будь должен начинать подсчет. Результат состоит в том, что, функционирования, он только реализует подсчет первых положений массива: от (0,0) до (2,2).

Решения есть некоторые и все происходят из-за того, что пересматривают способ действовать с возвратом.

Возможность состояла бы в том, чтобы предотвращать деление. Ты можешь предпочитать раскалывать на части массив в клетчатых сетках 2x2. Ты должен иметь в виду, что клетчатые сетки, которые остаются в краях массива, могут заканчивать тем, что 1x2 и 2x1.

// función auxiliar para sumar los valores de una matriz de, como mucho, 2x2
int suma2x2(MatrizEntero m, int f, int c, int nf, int nc)
{
  int toReturn = 0;

  int maxf = MIN(f+2,nf);
  int maxc = MIN(c+2,nc);

  for( int i=f ; i<maxf; ++i)
  {
    for( int j=c ; j<maxc; ++j)
    {
      toReturn += m[i][j];
    }
  }

  return toReturn;
}

// Función recursiva.
int equisuma(MatrizEntero m, int nf, int nc, int indexf, int indexc)
{
  int toReturn = suma2x2(m,indexf,indexc,nf,nc);

  if( indexc == 0 && indexf < nf) 
  {
    // Avanzamos al siguiente grupo por filas
    toReturn += equisuma(m,nf,nc,indexf+2,0);
  }

  if( indexc < nc )
  {
    // Avanzamos al siguiente grupo por columnas
    toReturn += equisuma(m,nf,nc,indexf,indexc+2);
  }

  return toReturn;   
}

Эта версия функционирует следующего способа:

  • Раздели массив групп 2x2
  • Начнись в (0,0) и инициализируй первое повторение продвигаясь из-за линий: (0,0) (2,0)...
  • Для каждого повторения в линиях, реализуй второе повторение из-за колонн: Для (0,0)-> (0,2), (0,4)... Для (2,0)-> (2,2), (2,4)...

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

Чтобы упрощать Ваше использование рекомендуемое в этих случаях состоит в том, чтобы создавать частную функцию, которая реализовывала бы возврат строго говоря и публичную функцию, которая опускала бы временную стоимость и начала в возврат:

// La función equisuma del ejemplo anterior renombrada
int equisuma_priv(MatrizEntero m, int nf, int nc, int indexf, int indexc);

// Función pública
int equisuma(MatrizEntero m, int nf, int nc)
{
  return equisuma_priv(m,nf,nc,0,0);
}

int main()
{
  // ...
  resultado=equisuma(mat,n,m);
  // ...
}

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

Приветствие.

2
ответ дан 24.11.2019, 12:44

Я не уверен, которого ты хочешь сделать, но предлагаю тебе какие-то изменения в твоем планировании:

Массив 2x2 может относиться друг к другу как array 4 элементов последующих.

typedef int Atom[4];

Больший массив 2x2 может относиться друг к другу как array Atom.

Сумма Atom тривиальная ([0] + [1] + [2] + [3])

Сумма массива - сумма iterativa нескольких Atom.

typedef int Atom[4];
typedef Atom *Array;

int sumaAtom( Atom v ) { return v[0] + v[1] + v[2] + v[3]; }

int sumaArray( Array, sizeX, sizeY ) {
  int x,
      y,
      acu = 0;

  for( x = 0; x < sizeX; ++x ) {
    for( y = 0; y < sizeY; ++y ) {
      acu += sumaAtom( Array[x][y] );
    }
  }

  return acu;
}

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

1
ответ дан 24.11.2019, 12:44
  • 1
    К несчастью, требуется использование возврата в этой проблеме. Я присоединяю изложение упражнения, спасибо за продвинутый: Ввиду массива целых чисел, больших или равных нулю dimensi и # 243; n NxN с N сила 2, говорят, что этот массив - “equisuma”, если элементы 4 субмассивов, которые составляют ее, складывают то же самое, и в свою очередь каждый субмассив - tambi и # 233; n equisuma. Adem и # 225; s, массив 2x2 всегда считается equisuma. –  Montu 06.11.2016, 14:26