数据结构与算法(JAVA篇)之递归算法(四)
/**
*
* @author SunnyMoon
*/
//////////////////////////////////////////////////////////////////////////////
/**
* 概念介绍:
*
* 消除递归:
* 一个算法作为一个递归的方法通常从概念上很容易理解,但实际使用中递归的效率不高,在这种
* 情况下,把递归算法转换成非递归的算法是非常有用的,这种转换经常用到栈。
*
* 递归和栈:
* 递归和栈之间有着紧密的联系,大部分的编译器使用栈实现递归的。
*
* 调用方法的时候发生什么:
* 1. 编译器会把这个方法所有当前参数及返回地址压入栈中;
* 2. 将控制权交给这个方法,方法通过获得栈顶元素值访问参数;
* 3. 方法运行结束的时候,值退栈,参数消失且控制权重新回到返回地址;
*
* 模拟递归方法:
* 可以将任意一个递归方法转换为非递归的基于栈的方法。在一些简单的情况可以完全消除栈,只
* 使用一个简单的循环,但是在很复杂的情况,算法中必须须要保留栈。本例子是简单的情况,可
* 以进一步完全消除栈。
*/
/////////////////////////////////////////////////////////////////////////////
/**
* 计算三角数字的问题:
* 递归算法描述如下
* int triiangle(int n){
* if(n==1)
* return 1;
* else
* return (n+triangle(n-1));
* }
*/
import java.io.*;
/**
* 模拟一个递归方法,通用的方式消除递归
*/
class Params {//封装了方法的返回地址和方法的参数
public int number;
public int returnAddress;
public Params(int num, int returnAdd) {
number = num;
returnAddress = returnAdd;
}
}
class StackX {//模拟递归时使用的栈
private int maxSize;
private Params[] stackArray;
private int top;
public StackX(int s) {
maxSize = s;
stackArray = new Params[maxSize];
top = -1;
}
public void push(Params p) {
stackArray[++top] = p;
}
public Params pop() {
return stackArray[top--];
}
public Params peek() {
return stackArray[top];
}
}
class StackTriangleApp {
static int theNumber;
static int theAnswer;
static StackX theStack;
static int logicAddress;
static Params theseParams;
public static void main(String[] args) throws IOException{//主方法
System.out.print("Number = ");
theNumber = getInt();
stackTriangle();
System.out.println("");
System.out.println("Trriangle = " + theAnswer);
}
@SuppressWarnings("empty-statement")
public static void stackTriangle() {//计算三角数字的方法,模拟递归方法
theStack = new StackX(100);
logicAddress = 1;//设置一个逻辑地址为入口地址
while (step() == false);
}
public static boolean step() {
switch (logicAddress) {
case 1:
theseParams = new Params(theNumber, 6);//设定循环返回的地址
theStack.push(theseParams);
logicAddress = 2;
break;
case 2:
theseParams = theStack.peek();
if (theseParams.number == 1) {
theAnswer = 1;
logicAddress = 5;
} else {
logicAddress = 3;
}
break;
case 3:
Params newParams = new Params(theseParams.number - 1, 4);
theStack.push(newParams);
logicAddress = 2;
break;
case 4:
theseParams = theStack.peek();
theAnswer = theAnswer + theseParams.number;
logicAddress = 5;
break;
case 5:
theseParams = theStack.peek();
logicAddress = theseParams.returnAddress;
theStack.pop();
break;
case 6:
return true;
}
return false;
}
public static String getString() throws IOException{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
public static int getInt() throws IOException{
String s=getString();
return Integer.parseInt(s);
}
}
/**
* 总结:
* 当要求效率的时候可以把弟归转化为基于栈的非递归,进而可以把基于栈的转化为仅有循环的
* 非递归,这种情况下效率是最高的。
* 但是一些复杂的情况可以转化为基于栈的非递归,但是无法消除栈的。
* 一些递归的算法是非常优秀的,比如分治算法。
*/