【发布时间】: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