我正在尝试将递归函数转换为伪代码中的非递归解决方案。我遇到问题的原因是该方法有两个递归调用。任何帮助都会很棒。感谢。
void mystery (int a, int b) {
if (b - a > 1) {
int mid = roundDown(a+b)/2;
print mid;
mystery(a, mid);
mystery(mid+1, b);
}
}
答案 0 :(得分:0)
这个似乎更有趣,它将导致以特定于递归函数的顺序显示从a到(b-1)的所有数字。请注意,所有“左”中点都在任何“正确”中点之前打印。
void mystery (int a, int b) {
if (b > a) {
int mid = roundDown(a+b)/2;
print mid;
mystery(a, mid);
mystery(mid+1, b);
}
}
例如,如果a = 0,b = 16,则输出为: 8 4 2 1 0 3 6 5 7 12 10 9 11 14 13 15
答案 1 :(得分:0)
这就是发生的事情。你有一根长杆,你把它分成两根。然后你把这两部分分成两部分。您对每个子部件执行此操作,直到该部件的长度变为1。
你会怎么做?
假设您必须在中点打破杆。我们将把标记切成垃圾箱以便进一步切割。注意:每个部件都会生成两个新部件,因此我们需要2个 n 框来存储子部件。
len = pow (2, b-a+1) // +1 might not be needed
ar = int[len] // large array will memoize my marks to cut
ar[0] = a // first mark
ar[1] = b // last mark
start_ptr = 0 // will start from this point
end_ptr = 1 // will end to this point
new_end = end_ptr // our end point will move for cuts
while true: //loop endlessly, I do not know, may there is a limit
while start_ptr < end_ptr: // look into bins
i = ar[start_ptr] //
j = ar[start_ptr+1] // pair-wise ends
if j - i > 1 // if lengthier than unit length, then add new marks
mid = floor ( (i+j) / 2 ) // this is my mid
print mid
ar[++new_end] = i // first mark --|
ar[++new_end] = mid - 1 // mid - 1 mark --+-- these two create one pair
ar[++new_end] = mid + 1 // 2nd half 1st mark --|
ar[++new_end] = j // end mark --+-- these two create 2nd pair
start_ptr = start_ptr + 2 // jump to next two ends
if end_ptr == new_end // if we passed to all the pairs and no new pair
break // was created, we are done.
else
end_ptr = new_end //else, start from sub prolem
PS:我还没试过这段代码。这只是一个伪代码。在我看来,它应该做的工作。如果你尝试一下,请告诉我。它将验证我的算法。它基本上是数组中的b树。
答案 2 :(得分:0)
将递归过程转换为迭代过程的texbook方法只是替换递归调用 堆栈并运行“do循环”直到堆栈为空。
尝试以下方法:
push(0, 16); /* Prime the stack */
call mystery;
...
void mystery {
do until stackempty() { /* iterate until stack is empty */
pop(a, b) /* pop and process... */
do while (b - a >= 1) { /* run the "current" values down... */
int mid = roundDown(a+b)/2;
print mid;
push(mid+1, b); /* push in place of recursive call */
b = mid;
}
}
原始函数有两次重复调用,为什么只有一个堆栈呢?忽略要求
第二次递归调用,你可以很容易地看到
第一个递归调用(mystery(a, mid);
)可以实现为一个简单的循环,其中b
假定mid
的值
在每次迭代中 - 没有其他东西需要被“记住”。所以把它变成一个循环,简单地推动
重叠到堆栈所需的参数,
添加外部循环以运行堆栈。完成。
通过一些创造性思维,任何递归函数都可以使用堆栈转换为迭代函数。
答案 3 :(得分:0)
此示例以递归方式分割一系列数字,直到范围缩小为单个值。输出显示数字的结构。单个值按顺序输出,但根据左侧第一个拆分函数进行分组。
void split (int a, int b)
{
int m;
if((b-a) < 2){ /* if size == 1, return */
printf(" | %2d", a);
return;
}
m = (a+b)/2; /* else split array */
printf("\n%2d %2d %2d", a, m, b);
split(a, m);
split(m, b);
}