c - 无法推断为什么我的递归函数中会出现段错误

标签 c recursion

我通过注释掉代码的特定部分对我的代码进行了一些实验。我发现当我用变量 j 注释掉 for 循环时不会发生段错误(代码中所示)。另外,当我注释掉函数中的递归部分(函数调用自身的行)时,即使存在 for 循环,也不会发生段错误。很明显,for 循环在函数的第二次或更高迭代中引起问题,但我不知道为什么。我能想到的一个可能的原因是发生了无限递归,但据我所知,这里没有发生无限递归。 我一直在尝试解决以下问题:https://www.codechef.com/problems/H1

#include<stdio.h>
 int prime1[]={3,5,7,11,13,17};
 int min=1000000000;   //just some large number
 void check(int *, int);
 void swap(int*, int, int);
 int prime(int);
 int main()
 {
  int T;
  scanf("%d", &T);
  for(int i=0; i<T; i++)
  {
   printf("\n");
   int arr[9];
   for(int j=0; j<9; j++)
   scanf("%d", &arr[j]);
   check(arr, 0);
   if(min==1000000000)
    min=-1;
   printf("%d\n", min);
  } 
 }

 void check(int arr[],int  step)       //step indicates the level of     
                                       //iteration
 {
  int k,  a[9];
  for(k=0; k<9; k++)
  {
   if(arr[k]!=k+1)
    break;
  }
  if(k==9)
  {
   if(step<min)
    min=step;
  }
  else
  {
   for(int i=0; i<8; i++)
   {
    if(i%3!=2)
    {
     if(prime(arr[i]+arr[i+1]))
     {
      for(int j=0; j<9; j++)          // segmentation fault 
       a[j]=arr[j];
      swap(a, i, i+1);
      check(a, step+1);
     }
    }
    if(i<=5)
    {
     if(prime(arr[i]+arr[i+3]))
     {
      for(int j=0; j<9; j++)          // segmentation fault
       a[j]=arr[j];
      swap(a, i, i+3);
      check(a, step+1);
     }
    }
   }  
  }  
 }
 int prime(int a)
 {
  for(int i=0; i<6; i++)
  {
   if(a==prime1[i])
    return 1;
  }
  return 0;
 }

 void swap( int a[], int b, int c)
 {
  int temp;
  temp=a[b];
  a[b]=a[c];
  a[c]=temp; 
 } 

最佳答案

你的算法永远运行,切换前两个图 block 。
我删除了一些循环,i=0k=0arr[] = {4,3,} 我们留下:

void check(int arr[], int step)
{
    int k, a[9];
    // arr[0] != 1, so k != 9, we fall in else { ... }
//  for (k = 0; k < 9; k++) {
//      if (arr[k] != k+1)
//          break;
//  }
//  printf("\n");
//  if (k == 9) {
//      if (step < min)
//          min = step;
//  } else {
        int i = 0;
//      for (int i = 0; i < 8; i++) {
//          if (i%3 != 2) {
//              if (prime(arr[i] + arr[i+1])) {
                    // i = 0, so i%3 != 2, so we fall in the first if
                    for (int j = 0; j < 9; j++)
                        a[j] = arr[j];
                    // you swap arr[0] with arr[1]
                    swap(a, i, i+1);
                    // and then you check again
                    check(a, step+1);
                    // and it runs so forever, never reaching this point
//              }
//          }
//          if (i <= 5) {
//              if (prime(arr[i] + arr[i+3])) {
//                  for (int j = 0; j < 9; j++)
//                      a[j] = arr[j];
//                  swap(a, i, i+3);
//                  check(a, step+1);
//              }
//          }
        }
    }
}

这个算法需要重新思考。当使用不同的步数运行时,您需要区分算法。最简单的方法是在每次检查时切换随机标题,更好的是构建一个正确的决策树,您可以记住切换了哪些标题。
您可能对某些感兴趣 proper indentation ,

关于c - 无法推断为什么我的递归函数中会出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51003431/

相关文章:

计算 L 的最大子集的算法,其中每对线段相交

Java Recursion - 几个递归调用的输出

c - 如何定义绝对值的顶点?

c - 在 C 中取消分配二维数组

c - C 中的 Struct 排序、比较和显示

java - 在 Java 中缺少从 bool 到 integer 的自动转换

Code::blocks 最大迭代次数

java - K-ary树递归打印方法到非递归

java - 如何返回斐波那契给定索引之前的每个索引值

c++ - 并行mergesort C++中的性能问题