【问题标题】:Fail in recursion with odd numbers奇数递归失败
【发布时间】:2020-06-27 10:01:03
【问题描述】:

我刚刚编写了这个函数来打印一个列表,其中包含ab 之间的数字。

void list(int a, int b){

  if(a == b){
    printf("%d", a);
  }else{
    if(a < b){
      printf("%d ", a);
      printf("%d ", b);
      list(a + 1, b - 1);
    }
    if(b < a){
      printf("%d ", a);
      printf("%d ", b);
      list(a - 1, b + 1);
    }
  }

}

当我从main 调用该函数时,它仅在数字数量为奇数时起作用。例如:

int main(){

  list(2, 8);

  return 0;
}

它工作正常并打印:2 8 3 7 4 6 5。但在这种情况下:

int main(){

  list(2, 7);

  return 0;
}

它永远打印2 7 3 6 4 5 5 4 4 5 5 4 4 5 5 4 4 5 5 4 4...

函数有什么问题??

【问题讨论】:

  • 应该很明显,如果两个数字都是奇数,或者都是偶数,它们将变得相等,但如果一个是奇数,另一个是偶数,它们将相互传递而不相等。例如,如果它们是 45,那么它们将变为 54

标签: c recursion


【解决方案1】:

因为它永远不会结束。当 a 和 b 之间的差异是奇数时,它们永远不会达到 == 条件并且它会永远持续下去。为了解决这个问题,你可以检查 a 和 b 是否会互相通过,这样:

void list(int a, int b)
{
    if(a == b)
        printf("%d", a);

    else if(a < b)
    {
        printf("%d ", a);
        printf("%d ", b);
        
        if (a + 1 != b)
            list(a + 1, b - 1);
    }

    else if(b < a)
    {
        printf("%d ", a);
        printf("%d ", b);
        
        if (b + 1 != a)
            list(a - 1, b + 1);
    }
}

【讨论】:

    【解决方案2】:

    每次进行迭代时,您都在对ab 进行减法/加法运算。这意味着当它是一个奇数和一对数时ab 将永远不会相同。我建议你在开始学习基本算法(特别是递归)时,在纸上尝试一些迭代。

    编辑: 一个建议是简单地添加一个退出子句(另一个 else if),如果 a 变得大于 b (反之亦然,取决于哪个数字),则退出递归更高,您可以将其保存为布尔值)。

    【讨论】:

      【解决方案3】:

      (2,7)

      2 7 3 6 4 5

      当a = 4, b = 5时,下一个是a = 5, b = 4,所以你得到了循环。

      试试这个:

      void list(int a, int b){ 
        if ( ( b-a ) % 2  == 0 ){ // even
          if(a == b){
          printf("%d", a);
        }else{
        if(a < b){
          printf("%d ", a);
          printf("%d ", b);
          list(a + 1, b - 1);
        }// if
          else if(b < a){
            printf("%d ", a);
            printf("%d ", b);
            list(a - 1, b + 1);
          }
        }
      }
      else { // odd
        if(a < b){
          printf("%d ", a);
          printf("%d ", b);
          list(a + 1, b - 1);
        }  // if
       }
      }
      

      【讨论】:

        【解决方案4】:

        在 a 不等于 b 的每一轮中,您将增加一个(a 或 b)并减少另一个。所以数字之间的差异现在减少了 2(或增加了 2)。简单的观察表明,为了终止重新调用函数,数字 (a,b) 必须相等。因此,对于差为 0(a=b,它不会再次调用该函数),开始时 a 和 b 之间的差应该是 2 的倍数。所以只有偶数或奇数都可以接受。在其他情况下,该函数将被一次又一次地调用并且特定的序列将重复(在您的情况下为 4 5 5 4)

        【讨论】:

          猜你喜欢
          • 2011-07-08
          • 2019-03-01
          • 2017-11-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多