zoukankan      html  css  js  c++  java
  • 【算法】转载:Iterative vs. Recursive Approaches

    Iterative vs. Recursive Approaches

    , 5 Nov 2007 CPOL
     
         
     
     

    Introduction

    This article was originally posted at blogs.microsoft.co.il/blogs/Eyal.

    Recursive function – is a function that is partially defined by itself and consists of some simple case with a known answer. Example: Fibonacci number sequence, factorial function, quick sort and more.
    Some of the algorithms/functions can be represented in an iterative way and some may not.

    Iterative functions – are loop based imperative repetitions of a process (in contrast to recursion which has a more declarative approach).

    Comparison between Iterative and Recursive Approaches from Performance Considerations

    Factorial

    //recursive function calculates n!
    static int FactorialRecursive(int n)
    {
        if (n <= 1) return 1;
        return n * FactorialRecursive(n - 1);
    }
    
    //iterative function calculates n!
    static int FactorialIterative(int n)
    {
        int sum = 1;
        if (n <= 1) return sum;
        while (n > 1)
        {
            sum *= n;
            n--;
        }
        return sum;
    }
    N Recursive Iterative
    10 334 ticks 11 ticks
    100 846 ticks 23 ticks
    1000 3368 ticks 110 ticks
    10000 9990 ticks 975 ticks
    100000 stack overflow 9767 ticks

    As we can clearly see, the recursive is a lot slower than the iterative (considerably) and limiting (stackoverflow).

    The reason for the poor performance is heavy push-pop of the registers in the ill level of each recursive call.

    Fibonacci

    //--------------- iterative version ---------------------    
    static int FibonacciIterative(int n)
    {
        if (n == 0) return 0;
        if (n == 1) return 1;
            
        int prevPrev = 0;
        int prev = 1;
        int result = 0;
            
        for (int i = 2; i <= n; i++)
        {
            result = prev + prevPrev;
            prevPrev = prev;
            prev = result;
        }
        return result;
    }
        
    //--------------- naive recursive version --------------------- 
    static int FibonacciRecursive(int n)
    {
        if (n == 0) return 0;
        if (n == 1) return 1;
            
        return FibonacciRecursive(n - 1) + FibonacciRecursive(n - 2);
    }
        
    //--------------- optimized recursive version ---------------------
    static Dictionary<int> resultHistory = new Dictionary<int>();
    
    static int FibonacciRecursiveOpt(int n)
    {
        if (n == 0) return 0;
        if (n == 1) return 1;
        if (resultHistory.ContainsKey(n)) 
            return resultHistory[n];
    
        int result = FibonacciRecursiveOpt(n - 1) + FibonacciRecursiveOpt(n - 2);
        resultHistory[n] = result;
            
        return result;
    }
    N Recursive Recursive opt. Iterative
    5 5 ticks 22 ticks 9 ticks
    10 36 ticks 49 ticks 10 ticks
    20 2315 ticks 61 ticks 10 ticks
    30 180254 ticks 65 ticks 10 ticks
    100 too long/stack overflow 158 ticks 11 ticks
    1000 too long/stack overflow 1470 ticks 27 ticks
    10000 too long/stack overflow 13873 ticks 190 ticks
    100000 too long/stack overflow too long/stack overflow 3952 ticks

    As before, the recursive approach is worse than iterative however, we could apply memorization pattern (saving previous results in dictionary for quick key based access), although this pattern isn't a match for the iterative approach (but definitely an improvement over the simple recursion).

    Notes

    1. The calculations may be wrong in big numbers, however the algorithms should be correct.
    2. For timer calculations, I used System.Diagnostics.Stopwatch.

    Points of Interest

    1. Try not to use recursion in system critical locations.
    2. Elegant solutions not always the best performing when used in "recursive situations".
    3. If you required to use recursion, at least try to optimize it with dynamic programming approaches (such as memorization).

    转自:http://www.codeproject.com/Articles/21194/Iterative-vs-Recursive-Approaches

     

    关于Tail Recursive

    It is possible that recursion will be more expensive, depending on if the recursive function is tail recursive (last line is recursive call). Tail recursion should be recognized by the compiler and optimized to its iterative counterpart (while maintaining the concise, clear implementation you have in your code).

    I would write the algorithm in the way that makes the most sense and is the most clear for the poor sucker (be it yourself or someone else) that has to maintain the code in a few months or years. If you run into performance issues, then profile your code, and then and only then look into optimizing by moving over to an iterative implementation. You may want to look into memoization and dynamic programming.

    转自: http://stackoverflow.com/questions/72209/recursion-or-iteration

    参考资料:

    尾调用:

    http://zh.wikipedia.org/wiki/%E5%B0%BE%E8%B0%83%E7%94%A8

    http://en.wikipedia.org/wiki/Tail_call

  • 相关阅读:
    期待着一个目标 和一个新生
    做一个真正意志坚强的人
    从猫叫、老鼠跑和人醒看观察者模式
    再看C++(6)操作符重载
    英尺
    再看C、C++、数据结构(三)
    一道比较有意思的打印题(不需要会很多计算机语言知识,简单的C就行)
    再看C++(四)const的终极使用
    再看C、C++、数据结构(二)
    再看C语言和数据结构(一)
  • 原文地址:https://www.cnblogs.com/yuzhangcmu/p/4043965.html
Copyright © 2011-2022 走看看