Iterative vs. Recursive Approaches

Eyal Lantzman, 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

Collapse | Copy Code
//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

Collapse | Copy Code
//--------------- 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 memorizationpattern (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

【算法】转载:Iterative vs. Recursive Approaches的更多相关文章

  1. A* 寻路算法[转载]

    A* 寻路算法 转载地址:http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html 原文地址: http://www.gamedev ...

  2. ICP算法(Iterative Closest Point迭代最近点算法)

    标签: 图像匹配ICP算法机器视觉 2015-12-01 21:09 2217人阅读 评论(0) 收藏 举报 分类: Computer Vision(27) 版权声明:本文为博主原创文章,未经博主允许 ...

  3. 【转】ICP算法(Iterative Closest Point迭代最近点算法)

    原文网址:https://www.cnblogs.com/sddai/p/6129437.html.转载主要方便随时可以查看,如有版权要求请及时联系. 最近在做点云匹配,需要用c++实现ICP算法,下 ...

  4. GJM : 数据结构 - 轻松看懂机器学习十大常用算法 [转载]

     转载请联系原文作者 需要获得授权,非法转载 原文作者将享受侵权诉讼 文/不会停的蜗牛(简书作者)原文链接:http://www.jianshu.com/p/55a67c12d3e9 通过本篇文章可以 ...

  5. 解读BloomFilter算法(转载)

    1.介绍 BloomFilter(布隆过滤器)是一种可以高效地判断元素是否在某个集合中的算法. 在很多日常场景中,都大量存在着布隆过滤器的应用.例如:检查单词是否拼写正确.网络爬虫的URL去重.黑名单 ...

  6. 数据结构图之三(最短路径--迪杰斯特拉算法——转载自i=i++

    数据结构图之三(最短路径--迪杰斯特拉算法)   [1]最短路径 最短路径?别乱想哈,其实就是字面意思,一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两 ...

  7. AStar算法(转载)

    以下的文章来至http://blog.csdn.net/debugconsole/article/details/8165530,感激这位博主的翻译,可惜图片被和谐了,所以为方便阅读,我重新把图片贴上 ...

  8. 浅谈MySQL索引背后的数据结构及算法(转载)

    转自:http://blogread.cn/it/article/4088?f=wb1 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储 ...

  9. 展开BOM并使用最终用量的算法(转载)

    本文系转载子ITPUB,如果有侵犯您权益的地方,烦请及时的告知与我,我即刻将停止侵权行为: 网址:http://www.itpub.net/thread-1020586-1-1.html http:/ ...

随机推荐

  1. 在Ubuntu Server是配置iptables防火墙

    iptables 是一个安装在Ubuntu Server上的默认防火墙.在正常的ubuntu安装过程中,iptables是被安装上了的,但是它默认允许所有的流量(不管防火墙是否是无效的) 关于ipta ...

  2. java中的Checked Exception和Unchecked Exception的区别

    Java 定义了两种异常: - Checked exception: 继承自 Exception 类是 checked exception.代码需要处理 API 抛出的 checked excepti ...

  3. JMeter入门:Java Request实例 (转)

    转自:http://blog.csdn.net/czp11210/article/details/26174969 目的:对Java程序进行测试:   一.核心步骤   1.创建一个Java工程: 2 ...

  4. PHP微信公众平台

    微信公众平台客户中心微信公众平台开发文档微信公众平台自定义菜单微信公众平台开发(一) 配置接口微信公众平台开发(二) 微信公众平台示例代码分析微信公众平台开发(三) 订阅事件(subscribe)处理 ...

  5. redis阻塞bgsave与bsrewriteaof

    问题描述: redis在进程偶尔会出现2个进程redis-server \ redis-bgsave Redis 首先 fork 一个子进程, 并在该子进程里进行归并和写持久化存储设备(如硬盘)的. ...

  6. php调试利器Xhprof的安装与使用

    一.安装xhprof wget http://pecl.php.net/get/xhprof-0.9.4.tgz tar -zxvf xhprof-0.9.4.tgz cd xhprof-0.9.4/ ...

  7. C# 生成 DataMatrix 格式的二维码

    该文主要是利用OnBarcode.dll 生成 DataMatrix 格式的二维码的一些简单方法和操作技巧.关于QrBarcode的二维码比较常见和简单,网上有很多资源. 1.附件为dll 2.利用上 ...

  8. c语言格式大整理

    1.C语言中,非零值为真,真用1表示:零值为假,假用0表示. 2.转义字符参考: \a 蜂鸣,响铃 \b 回退:向后退一格 \f 换页 \n 换行 \r 回车,光标到本行行首 \t 水平制表 \v 垂 ...

  9. 使用ajax和window.history.pushState无刷新改变页面内容和地址栏URL (转)

    在访问现在很火的google plus时,细心的用户也许会发现页面之间的点击是通过ajax异步请求的,同时页面的URL发生了了改变.并且能够很好的支持浏览器的前进和后退.不禁让人想问,是什么有这么强大 ...

  10. python练习笔记——map | sum | pow 的应用

    1 函数简要 map 函数  | sum 函数  |  pow函数  | lambda函数 2 简要计算 2.1 1^2 + 2^2 + 3^2 .....9^2 方法1 print([pow(x,2 ...