把递归算法转化为非递归算法, 有如下两种基本方法:
1)通过分析, 用迭代的方式自底向上. 有时需用栈保存参数
2)模拟函数调用过程, 用栈保存入参
尾递归:
一个函数只在return处调用自身。很多编译器就能将其转换为迭代
T tailRecursive(U x, V y) { if (bar(x, y)) { return exit(x,y); } else { ... // block 1 return tailRecursiveFoo(w, z); } } To: T Iterative(U x, V y) { while (!bar(x, y)) { // 调用递归子函数的条件if -> while ... // block 1 x = w; // 传入递归子函数的参数 y = z; } return exit(x,y); // 递归出口 }
更通用点的伪代码:
T recursiveFoo(U param1, V param2){ U local1; V local2; ... // code block 1 recursiveFoo (local1, local2); ... // code block 2 recursiveFoo (param1, local2); ... // code block 3 recursiveFoo (local1, param2); ... // code block 4 } To: T iterativeFoo (U param1, V param2) { U local1; V local2; Stack stk; stk.push(javaBean:{param1, param2, local1, local2, 1}); // 进入函数, 第一次调用: 创建栈并将局部变量压栈 while (!stk.empty()) { // 循环直至栈空 + 弹栈 FooStackInfo stkTop = stk.pop(); param1 = stkTop.param1; param2 = stkTop.param2; local1 = stkTop.local1; local2 = stkTop.local2; switch (stkTop.location) { // 递归块->switch-case包裹 case 1: ... // code block 1 //向前匹配块 stk.push(javaBean:{param1, param2, local1, local2, 2}); //第二次调用 stk.push(javaBean:{local1, local2, local1, local2, 1}); //传参 break; case 2: ... // code block 2 //向前匹配块 stk.push(javaBean:{param1, param2, local1, local2, 3}); //第三次调用 stk.push(javaBean:{param1, local2, local1, local2, 1}); //传参 break; case 3: ... // code block 3 //向前匹配块 stk.push(javaBean:{param1, param2, local1, local2, 4}); //第四次调用 stk.push(javaBean:{local1, param2, local1, local2, 1}); //传参 break; case 4: ... // code block 4 //程序末尾(无匹配) break; } } }
注: 如果递归子函数都在一起且在递归母函数程序的末尾,则无需记录调用位置且无需使用switch case,只需要push。