【问题标题】:Converting recursion to iteration将递归转换为迭代
【发布时间】:2016-01-26 06:39:46
【问题描述】:

我做了一些阅读,并了解到将递归转换为迭代的最佳方法是使用堆栈。但是,由于返回值的使用方式,很难实现。任何帮助都会很棒。这是递归函数:

public Complex[] fft(Complex[] x, int L) {
    int ii;
    int kk = 0;
    int N = x.Length;

    Complex[] Y = new Complex[N];

    if (N == 1) {
        Y[0] = x[0];
    } else {

        Complex[] E = new Complex[N / 2];
        Complex[] O = new Complex[N / 2];
        Complex[] even = new Complex[N / 2];
        Complex[] odd = new Complex[N / 2];


        for (ii = 0; ii < N; ii++) {
            if (ii % 2 == 0) {
                even[ii / 2] = x[ii];
            }
            if (ii % 2 == 1) {
                odd[(ii - 1) / 2] = x[ii];
            }
        }

        E = fft(even, L);   // RECURSION HERE
        O = fft(odd, L);    // RECURSION HERE

        // RECURSION RESULTS USED HERE
        for (kk = 0; kk < N; kk++) {
            Y[kk] = E[(kk % (N / 2))] + O[(kk % (N / 2))] * twiddles[kk * (L / N)];
        }
    }

    return Y;
}

下面的代码不起作用,但它显示了我到目前为止的尝试

public Complex[] fft2(Complex[] x, int L) {
    Stack<Complex[]> stack = new Stack<Complex[]>();
    stack.Push(x);

    int ii;
    int kk;
    int N;

    while (stack.Count > 0) {
        x = stack.Pop();
        kk = 0;
        N = x.Length;

        Complex[] Y = new Complex[N];

        if (N == 1) {
            Y[0] = x[0];
        } else {

            Complex[] E = new Complex[N / 2];
            Complex[] O = new Complex[N / 2];
            Complex[] even = new Complex[N / 2];
            Complex[] odd = new Complex[N / 2];

            for (ii = 0; ii < N; ii++) {
                if (ii % 2 == 0) {
                    even[ii / 2] = x[ii];
                }
                if (ii % 2 == 1) {
                    odd[(ii - 1) / 2] = x[ii];
                }
            }

            stack.Push(even);
            stack.Push(odd);

            // E = fft2(even, L);
            // O = fft2(odd, L);

            for (kk = 0; kk < N; kk++) {
                Y[kk] = E[(kk % (N / 2))] + O[(kk % (N / 2))] * twiddles[kk * (L / N)];
            }
        }
    }

    return Y;
}

【问题讨论】:

  • 您能否展示任何您为转换它所做的工作?
  • 是的,我不打算添加它以使问题更简单,因为我的解决方案当然不起作用。无论如何,我只是将它附加到我的问题详细信息中。
  • @ThomasLevesque:任何递归方法都可以转换为迭代方法。提示:你能把方法转换成延续传递风格吗?如果答案是肯定的,那么你能看看如何将 CPS 版本转换为迭代算法吗?
  • @John:您不想将其转换为 CPS;我的观点是,Thomas 认为进行两次递归调用的方法不能进行迭代的想法是错误的;所有递归方法都可以转换为 CPS,所有 CPS 程序都可以迭代,但这一事实对编译器设计人员有用,而不是对业务线程序员有用。你应该做的是简化你的算法到它的本质。
  • 如果你有兴趣学习CPS,这很有趣,我在这里为JavaScript程序员做一个温和的介绍:blogs.msdn.com/b/ericlippert/archive/tags/…从底部开始。

标签: c# algorithm recursion iteration tail-recursion


【解决方案1】:

当你查看代码时,本质上,递归性得到了,并且停止像这样:

N 的数组 => 通过递归,计算出2个N/2的数组,然后将它们组合起来

当N==1时,结束。

然后,您计算每 2. N/2, 4. N/4, ... 2^n 。 N/2^n ,其中 n=log2(N)

数据似乎不可重复使用,所以你必须计算 2^n 个数组。

如果您的大小是 2 的幂,例如 64,您将必须计算 64 个数组,然后是 32、16、8、4、2、1,然后是 127 次操作 (=2^(n+1)- 1).

所以问题变成了:如何将二叉树中的递归操作转换为迭代。

我从 SO 中选择了其他具有相同普遍问题的帖子:您可以在那里找到算法和代码:

Post order traversal of binary tree without recursion

Convert recursive binary tree traversal to iterative

从递归转换为迭代的更一般的问题取决于递归的算法,以及数据是否可重用。

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 2017-03-05
    • 2016-06-29
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    相关资源
    最近更新 更多