Java将递归改成循环的通用方法

用Stack或LinkedList来实现内存中的出栈入栈过程,即可将递归改成循环。

正式开始前先厘清几个概念:
循环(loop) - 最基础的概念, 所有重复的行为
递归(recursion) - 在函数内调用自身, 将复杂情况逐步转化成基本情况
(数学)迭代(iterate) - 在多次循环中逐步接近结果
(编程)迭代(iterate) - 按顺序访问线性结构中的每一项
遍历(traversal) - 按规则访问非线性结构中的每一项
确切地说,递归也属于循环。下文中的「循环」特指非递归的循环。

第一个例子用求阶乘,顺便加了迭代方法。
[java] view plain copy
import java.util.Stack;  
  
public class Factorial{  
    public static void main(String[] args){  
        Factorial f = new Factorial();  
        System.out.println(f.recursion(5));  
        System.out.println(f.loop(5));  
        System.out.println(f.iteration(5));  
    }  
  
    /** 
     * 递归求阶乘 
     */  
    public int recursion(int n){  
        if (n == 1) return 1;  
        return recursion(n-1) * n;  
    }  
  
    /** 
     * 循环求阶乘 
     */  
    public int loop(int n){  
        Stack<Integer> stack = new Stack<Integer>();  
        int result = 1;  
        stack.push(n);  
        while(!stack.isEmpty()){  
            n = stack.pop();  
            result *= n;  
            if (n > 1) stack.push(n-1);  
        }  
        return result;  
    }  
  
    /** 
     * 迭代求阶乘 
     */  
    public int iteration(int n){  
        int result = 1;  
        for(int i = 1; i <= n; i++){  
            result *= i;  
        }  
        return result;  
    }  
}  


第二个例子是快速排序。递归快排大量数量时,容易爆栈。这时可以改成循环。
[java] view plain copy
import java.util.Random;  
  
public class Sorts{  
    private static Random rand = new Random();  
  
    public static void main(String[] args){  
        int[] a = {49,38,65,97,76,13,27,49,78,34,12,64,5,4,62  
            ,99,98,54,56,17,18,23,34,15,35,25,53,51};   
        quickSort(a);  
        System.out.println(Arrays.toString(a));  
        int[] a = {49,38,65,97,76,13,27,49,78,34,12,64,5,4,62  
            ,99,98,54,56,17,18,23,34,15,35,25,53,51};   
        quickSortByLoop(a);  
        System.out.println(Arrays.toString(a));  
    }  
  
    /** 
     * 快速排序 
     * 递归实现 
     */  
    private static void quickSort(int[] arr, int start, int end){  
        if (start >= end) return;  
        int base = arr[start + rand.nextInt(end-start+1)]; //中轴值  
        int left = start, right = end; //指示左右两端未排序的边界索引  
        int i = start; // 用于排序  
        while(i <= right){  
            if (arr[i] < base){ //小于中轴值则移到左侧  
                swap(arr, left++, i++);  
            }else if (arr[i] > base){ //大于中轴值则移到右侧  
                swap(arr, right--, i); //当前i位置的值未排序,故i不自增  
            }else{  
                i++;  
            }  
        }  
        //排完后left左侧均为小于base的数,right右侧均为大于base的数  
        quickSort(arr, start, left-1);  
        quickSort(arr, right+1, end);  
    }  
  
  
    /** 
     * 快速排序 
     * 循环实现 
     */  
    private static quickSortByLoop(int[] arr){  
        Stack<Integer> stack = new Stack<Integer>();  
        int start = 0;  
        int end = arr.length - 1;  
        stack.push(start);  
        stack.push(end);  
        while(!stack.isEmpty()){  
            end = stack.pop(); // 顺序很重要  
            start = stack.pop();  
            if (start < end){ // 开始排序  
                int i = start;  
                int base = arr[start + rand.nextInt(end-start+1)]  
                int left = start;  
                int right = end;  
                while(i <= right){  
                    if (arr[i] < base){  
                        swap(arr, left++, i++);  
                    }else if (arr[i] > base){  
                        swap(arr, right--, i);  
                    }else {  
                        i++;  
                    }  
                }  
                // ----右半边----  
                stack.push(right + 1);  
                stack.push(end);  
                // ----左半边----  
                stack.push(start);  
                stack.push(left - 1);  
            }  
        }  
    }  
}  

猜你喜欢

转载自luckybrown.iteye.com/blog/2332003