C中递归过程中的递归调用

时间:2012-02-02 09:09:44

标签: c recursion

所以我遇到了一个问题,在我看来,我需要在另一个内部使用递归程序。我有一个4x4矩阵作为一个平面数组。一些条目将是非零,但每次都不是相同的数量。对于每个非零条目,都有一个我可以用该特定值交换的候选列表。当然,我可以为所有非零条目执行此操作。我想要非零条目的所有可能的交换组合,以递归到程序的下一级。

例如,对程序的一个级别的输入是

2 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0

假设2的交换候选者是{1,3,4},那么,对于每个值,我想用该值替换2并递归到下一个级别,但首先我将申请转换,导致可能存在或多或少的非零值。

例如,当我们将2替换为3时,我们会得到(转换前后)

3 0 0 0       5 2 1 8
0 0 0 0  ->   0 0 0 0
0 0 0 0       0 0 0 0
0 0 0 0       0 0 0 0

并且在我们用2替换3的情况下,这是我们在下一级递归中使用的,其中5,2,1和8中的每一个都有自己的替换候选者,依此类推。

所以我很难得到的是这个;我认为我需要使用递归来尝试矩阵中非零值的所有可能交换组合,但同时,对于它们中的每一个,递归到“外部过程”的下一级。 / p>

关于如何实现这一目标的任何提示?我用C编码,但C ++也可以接受。

4 个答案:

答案 0 :(得分:1)

听起来你想要做一些像(假的代码):

    DoThing(int[,] a, int rows, int cols) {
      for(int i=0;i<rows;i++) {
        for(int j=0;j<cols;j++) {
          if (a[i,j]>0) {
            int[] replacements;
            int size = GetReplacements(a[i,j], replacements);
            for (int k=0;k<size;k++) {
              int[rows,cols] r = CopyArray(a, rows, cols);
              r[i,j]=replacements[k];
              Transform(r, rows, cols);
              DoThing(r, rows, cols);
            }
         }
       }
     }
  }

或者如果你在同一个阵列上操作:

DoThing(int[,] a, int rows, int cols) {
  for(int i=0;i<rows;i++) {
    for(int j=0;j<cols;j++) {
      if (a[i,j]>0) {
        int[] replacements;
        int size = GetReplacements(a[i,j], replacements);
        for (int k=0;k<size;k++) {
          a[i,j]=replacements[k];
          Transform(a, rows, cols);
          DoThing(a, rows, cols);
        }
     }
   }
 }

}

这将继续跟随第一个非零条目中的第一个替换及其所有相应的替换,然后再返回并在第一个字段上执行第二次替换......

编辑:另一个版本

This code (c# Console app)首先确定替换可以发生的位置以及可以在每个位置替换哪些数字,然后生成一个包含所有可能方法的数组来组合这些替换,然后遍历每个可能性,在每个位置进行替换在原始矩阵中,然后在进行下一次迭代之前在新替换的矩阵上递归。

代码很容易转换为c ++(out和ref参数将是int&amp;或int *)。

要小心,引入替代周期非常容易。该示例专门设置为最终终止,但您可以轻松创建替换周期,这将导致算法运行直到溢出,例如:1 - &gt; {2,3},2 - &gt; {1,3},3-> {0,0}将'永远'将1替换为2,然后将2替换为1,然后将1替换为2,等等。增加的MaxRecursion深度或其他一些全局保护可能有所帮助。

性能可能会得到优化,我这样做很快而且很脏。

答案 1 :(得分:0)

尝试摆脱递归:使用stack data structure,例如std::vector<>(在C ++中)来记忆下一步做什么而不是调用递归过程。如果递归调用在过程结束时(tail recursion),这是相当简单的,如果在递归之后有代码,则需要更多的工作。

这是适用于所有递归过程的一般策略,我不是试图将它应用于给定的问题。

答案 2 :(得分:0)

递归是处理矩阵的一种简单方法,但请注意您的内存使用情况。程序的每个“级别”将跟踪所有先前的更改,仅在4或5级之后可能很重...

如果我做对了,你的算法看起来像这样:

StartProcedure:

  • 阅读矩阵
  • 有下一个非零值吗?
    • 是:调用ReplaceProcedure(valueX,valueY)
    • 否:跳到最后

替换Procecure:

  • 列出候选人名单
  • 每位候选人:
    • 转换当前矩阵
    • 替换为候选人
  • 返回StartProcedure

迭代可以。但是当你在“转换”矩阵时有一个矩阵和重叠值(显然),你选择递归并复制矩阵:最后你需要多个矩阵还是你有两个矩阵的合并规则? / p>

在递归中,算法看起来像:

StartProcedure:

  • 阅读矩阵
  • 有下一个非零值吗?
    • 是:调用ReplaceProcedure(valueX,valueY)
    • 否:跳到最后

ReplaceProcedure:

  • 列出候选人名单
  • 每位候选人:
    • 转换当前矩阵
    • ReplaceCandidate(valueX,valueY)

ReplaceCandidate:

  • 用候选人替换价值
  • 从valueX,valueY
  • 开始调用StartProcedure

答案 3 :(得分:0)

简单(资源密集型)管理解决方案:将数组包装在结构中,以便在每个递归级别拥有不同的数组。

struct arraywrap {
    int data[4][4];
};

int recurse(struct arraywarp arg);

int main(void) {
    struct arraywrap flatarray = {0};
    recurse(flatarray);
}