<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>Joard</title>
    <description></description>
    <link>http://joard.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>设计模式学习小结</title>
        <author>Joard</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://joard.javaeye.com">Joard</a>&nbsp;
          链接：<a href="http://joard.javaeye.com/blog/168069" style="color:red;">http://joard.javaeye.com/blog/168069</a>&nbsp;
          发表时间: 2008年03月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这段时间重新翻看了一下阎宏的《Java与模式》，把里面我敢兴趣的地方摘抄与此。<br />首先<br /><div class="quote_title">Gof 写道</div><div class="quote_div">本书中的<span style="color: #ff0000"><strong>设计模式</strong></span>是<span style="color: #3366ff">对被用来在特定场景下解决一般设计问题的类和相互通信的对象的描述。</span></div><br /><br /><span style="font-size: small"><strong>一.面向对象软件设计的核心问题：可维护性(Maintainability)与可复用性(Reuseability)。</strong></span><br /><br /><span style="font-size: small"><strong>二.维护性较差的原因：</strong></span><br />过于僵硬 Rigidity   &lt;---> 可扩展性 Extensibility<br />过于脆弱 Fragility  &lt;---> 灵活性   Flexibility<br />复用率低 Immobility<br />粘度过高 Viscosity  &lt;---> 可插入性 Pluggability<br /><br /><span style="font-size: small"><strong>三.面向对象设计的几个原则</strong></span><br />开-闭原则         Open-Closed Principle              OCP<br />里氏代换原则      Liskov Substitution Principle      LSP<br />依赖倒转原则      Dependency Inversion Principle     DIP<br />接口隔离原则      Interface Segregation Principle    ISP<br />组合/聚合复用原则 Composition/Aggregation Principle  CARP<br />迪米特法则        Law of Demeter                     LoD<br />可扩展性：OCP, LSP, DIP,CARP<br />灵活性：OCP, ISP,LoD<br />以上两点的交集就是&ldquo;可维护性复用&rdquo;。<br /><br /><span style="font-size: small"><strong>1.开闭原则 OCP</strong></span><br />一个软件的实体应当对扩展开放，对修改关闭。<br />Software entities should be open for extension,but closed for modification.<br /><br />对可变性的封装原则 Principle of Encapsulation of Variation   EVP<br />EVP实际上是设计模式的<span style="color: #ff0000">主题</span>，换言之，所有的设计模式都是对不同的可变性的封装，从而使系统在不同的角度上达到OCP要求。<br /><br /><span style="font-size: small"><strong>2.里氏代换原则 LSP</strong></span><br />如果对每一个类型为T1的对象o1，都有类型为T2的对象o2，使得以T1定义的所有程序P在所有对象o1都代换成o2时，程序P的<span style="color: #ff0000">行为没有变化</span>，那么类型T2是T1的子类型。<br />LSP要求凡是基类使用的地方，子类型一定适用。<br /><span style="color: #3366ff">LSP是一条非常严格的原则，要求基类变为子类的时候，其程序行为不发生改变。在oop时并没有严格按照LSP来做。</span><br /><br /><span style="font-size: small"><strong>3.依赖倒转原则 DIP</strong></span><br />表述1：抽象不应当依赖于细节，细节应当依赖于抽象。<br />       Abstractions should not depend upon details, details should depend upon abstractions.<br />表述2：要针对接口编程，不要针对实现编程。<br />       Program to an interface, not an implementation.<br /><br /><span style="font-size: small"><strong>4.接口隔离原则 ISP</strong></span><br />使用多个专门的接口比使用单一的总接口要好。<br />一个类对另一个类的依赖性应当是建立在最小接口上的(LoD)。<br /><br /><span style="font-size: small"><strong>5.合成/聚合复用原则 CARP</strong></span><br />= 合成复用原则 Composite Reuse Principle CRP<br />要尽量使用合成/聚合，尽量不要使用继承。<br />继承的优点：①新类易实现. ②易修改或扩展<br />      缺点：①继承复用破环包装，白箱复用.<br />            ②超类发生变化，子类不得不改变.<br />            ③继承的实现是静态的，不能在运行时改变.<br /><span style="color: #3366ff">优缺点的②是相互对应的。<br /></span><br /><span style="font-size: small"><strong>6.迪米特法则 LoD</strong></span><br />= 最少知识原则 Least Konwledge Principle<br />一个对象应当对其他对象有尽可能少的了解。<br />表述：<br />①只与你直接的朋友们通信 Only talk to your immediate friends<br />②不要跟陌生人说话 Don's talk to strangers<br />③每一个软件单位对其他的单位都只有最少的知识，而且局限于那些与本单位密切相关的软件单位。<br />LoD的<span style="color: #ff0000">实质</span>是控制对象之间的信息流量，流向及信息的影响。<br />①优先考虑将一个类设置成不变类.<br />②尽量降低类/成员的访问权限.<br /><br />要想恰到好处地在一个系统里面使用设计模式，必须做到以下几点：<br />①完全了解面临的问题，这就是说要完全了解具体情况。如果不完全了解所面临的难题，怎么能谈得上解决问题呢？<br />②完全了解模式，这就是说要十分懂得理论。如果不完全懂得所使用的理论，怎么能够正确地应用这一理论呢？<br />③非常了解怎样使用设计模式解决实际的问题，这就是说要将模式理论与具体系统需求情况相结合。如果设计师不知道一个设计模式怎样对系统设计有帮组的话，最好不要使用这个模式。不要只是因为想在简历上写上设计模式方面的经验就盲目地使用模式。<br /><br />来看看gof是怎么说的<br /><div class="quote_title">Gof 写道</div><div class="quote_div">通常你通过引入额外的间接层获得灵活性和可变性的同时，你也使设计变得更复杂并/或牺牲了一定的性能。一个设计模式只有当它提供的灵活性是真正需要的时候，才有必要使用。</div><br /><br /><span style="font-size: small"><strong>写在最后</strong></span><br />原本想写个总结什么的，写写各种模式的设计，再举个简单例子什么的。最后大感不必（神啊！原谅我的懒惰吧！）在这次翻看设计模式时，最大的感受是&ldquo;万变不离其中&rdquo;。很多设计模式在设计时都遵循上面列举的几个<span style="color: #3366ff">原则</span>，不同的模式对原则有不同的侧重，在学习时可以运用这些原则去分析这些既有的设计模式，判断它们的优缺点。进而提高自己的分析和设计能力，毕竟GOF的23种设计模式也有它的局限，总会有新的问题待自己去解决。再说设计模式本身也不是语言中立的，先不提OOP与FP，就连OOP之间，有些设计模式就不是互通的，当然这些都是题外话了。<br />最后总结一下自己学习设计模式的阶段过程：<br /><span style="color: #3366ff">GOF---> Java与模式 ---> 面向对象设计的基本原则 ---> 用原则自行分析既有设计模式 ---> 忘掉设计模式！ ---> 开始动手干！</span><br />最后带！号的阶段还没有开始处于&ldquo;意淫&rdquo;阶段，不过当当&ldquo;自淫者&rdquo;也不妨，别怕失败，工资是靠失败积累起来地！
          <br/>
          <span style="color:red;">
            <a href="http://joard.javaeye.com/blog/168069#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 05 Mar 2008 10:26:22 +0800</pubDate>
        <link>http://joard.javaeye.com/blog/168069</link>
        <guid>http://joard.javaeye.com/blog/168069</guid>
      </item>
      <item>
        <title>粗看递归</title>
        <author>Joard</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://joard.javaeye.com">Joard</a>&nbsp;
          链接：<a href="http://joard.javaeye.com/blog/96491" style="color:red;">http://joard.javaeye.com/blog/96491</a>&nbsp;
          发表时间: 2007年07月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          &nbsp;&nbsp; 第一次写blog，答应朋友Leon，写一篇粗略地介绍&ldquo;递归（recursion）&rdquo;的文章。<br />
&nbsp;&nbsp; 递归，一种古老但依旧实用的东东，很多算法用递归方法表示，用递归写的程序也很容易让人理解。<br />
&nbsp;&nbsp; 递归的优美在于使得程序更简洁，同时也更自然。尤其是在处理层次性数据的时候，十分强大。当然，递归的缺点也十分明显--性能问题。在性能这个问题点上， 有一种手段能适当改善递归的性能--尾递归（尾递归的概念将在下文解释）。关于优缺点就此打住，还是很容易理解，我就不婆婆妈妈的罗嗦了，我直接切入正 题。<br />
&nbsp;&nbsp;&nbsp; <strong><font size="4"><br />
什么是递归？</font></strong><br />
&nbsp;&nbsp;&nbsp; 在这里我们区分一下几个概念&ldquo;递归过程&rdquo;和&ldquo;递归计算过程&rdquo;以及相对应的&ldquo;迭代计算过程&rdquo;。<br />
&ldquo;<font color="#ff0000">递归过程</font>&rdquo;通常是指某个过程（方法）的定义直接或间接地引用了该过程（方法）本身。在本文中如非特别说明，&ldquo;递归&rdquo;这个词泛指一个或某种&ldquo;递归过程&rdquo;，而在描述递归型计算过程的时候都会用&ldquo;递归计算过程&rdquo;。<br />
下面是一个array求和的递归方法<br />
<div class="code_title">ruby 代码</div>
<div class="dp-highlighter">
<ol class="dp-rb" start="1">
    <li class="alt"><span><span class="keyword">def</span><span>&nbsp;sum(arr)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;arr.empty?&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;arr.shift&nbsp;+&nbsp;sum(arr)&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
这是一个递归，同时也是递归计算过程的递归。来看看sum函数在1..5上的求值过程<br />
<div class="code_title">ruby 代码</div>
<div class="dp-highlighter">
<ol class="dp-rb" start="1">
    <li class="alt"><span><span>[1,2,3,4,5]&nbsp;&nbsp;</span></span></li>
    <li class=""><span>1&nbsp;+&nbsp;sum([2,3,4,5])&nbsp;&nbsp;</span></li>
    <li class="alt"><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;sum([3,4,5]))&nbsp;&nbsp;</span></li>
    <li class=""><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;(3&nbsp;+&nbsp;sum([4,5])))&nbsp;&nbsp;</span></li>
    <li class="alt"><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;(3&nbsp;+&nbsp;(4&nbsp;+&nbsp;sum([5]))))&nbsp;&nbsp;</span></li>
    <li class=""><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;(3&nbsp;+&nbsp;(4&nbsp;+&nbsp;(5&nbsp;+&nbsp;sum[]))))&nbsp;&nbsp;</span></li>
    <li class="alt"><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;(3&nbsp;+&nbsp;(4&nbsp;+&nbsp;(5&nbsp;+&nbsp;0))))&nbsp;&nbsp;</span></li>
    <li class=""><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;(3&nbsp;+&nbsp;(4&nbsp;+&nbsp;5)))&nbsp;&nbsp;</span></li>
    <li class="alt"><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;(3&nbsp;+&nbsp;9))&nbsp;&nbsp;</span></li>
    <li class=""><span>1&nbsp;+&nbsp;(2&nbsp;+&nbsp;12)&nbsp;&nbsp;</span></li>
    <li class="alt"><span>1+&nbsp;14&nbsp;&nbsp;</span></li>
    <li class=""><span>15&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
通过这个求值过程，很容易看出sum函数有明显的展开和收缩（收敛）过程。类似这样先展开/后收缩（收敛）的推迟求值的过程就是&ldquo;<font color="#ff0000">递归计算过程</font>&rdquo;。<br />
&nbsp;&nbsp;&nbsp; 知道了什么是&ldquo;递归计算过程&rdquo;后，再来瞧瞧&ldquo;迭代计算过程&rdquo;。代码在这里是最佳的说明，我们稍微改变一下sum函数用迭代计算过程来求值。<br />
<div class="code_title">ruby 代码</div>
<div class="dp-highlighter">
<ol class="dp-rb" start="1">
    <li class="alt"><span><span class="keyword">def</span><span>&nbsp;sum_iter(arr,&nbsp;resu&nbsp;=&nbsp;0)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;arr.empty?&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;resu&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;resu&nbsp;+=&nbsp;arr.shift&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;sum_iter(arr,&nbsp;resu)&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
ps:<span><span>sum_iter的写法有时候也会被称为尾递归写法。怎么又是尾递归？稍安毋躁，我发誓接下来我一定会说到&ldquo;尾递归&rdquo;的！<br />
<br />
</span></span> 它在1..5上的求值过程如下<br />
<div class="code_title">ruby 代码</div>
<div class="dp-highlighter">
<ol class="dp-rb" start="1">
    <li class="alt"><span><span>[1,2,3,4,5]&nbsp;&nbsp;</span></span></li>
    <li class=""><span>[&nbsp; 2,3,4,5] +&nbsp;1&nbsp;&nbsp;</span></li>
    <li class="alt"><span>[&nbsp;&nbsp;&nbsp; 3,4,5]&nbsp;+&nbsp;3&nbsp;&nbsp;</span></li>
    <li class=""><span>[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4,5]&nbsp;+&nbsp;6&nbsp;&nbsp;</span></li>
    <li class="alt"><span>[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5]&nbsp;+&nbsp;10&nbsp;&nbsp;</span></li>
    <li class=""><span>[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ]&nbsp;+&nbsp;15&nbsp;&nbsp;</span></li>
    <li class="alt"><span>15&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
在这个计算过程中，平没有明显的展开和收缩（收敛）过程，在整个运行轨迹中我们只需保存变量resu。这种所有程序状态可以用固定个数的状态变量，以及一套固定的状态变量的修改规则就是&ldquo;<font color="#ff0000">迭代计算过程</font>&rdquo;。相比递归计算过程，迭代计算过程有一个优点就是可以保存程序运行中的某个状态，然后下次运行的时候可以直接传递这个中间状态给该过程以恢复上次运算。你可以传递[4,5]和6给<span><span>sum_iter，它仍然能计算出15，而你传递[4，5]给sum，结果是9。<br />
<br />
<font size="4"><strong>线性递归和树形递归</strong></font><br />
</span></span>&nbsp;&nbsp;&nbsp; 也许当你看到sum和<span><span>sum_iter的时候，你更喜欢用for，foreach和while这样的循环来处理。实际上有一部分递归可以很容易地转换为循环，然而另一部递归却并不那么容易的进行转换。是否能容易转换为循环，取决于它是否是迭代/递归计算过程和</span></span>线 性/树形递归。毫无疑问，拥有迭代计算过程的递归可以迅速转换为循环。迭代计算过程的递归和循环处理基本上是等价的，因此某个递归能不能转换为 迭代计算过程的递归也就决定了它能不能转换为循环处理。至于为什么要把递归转换为循环处理，可以看看【然而它工作得不过好】。<br />
&nbsp;&nbsp;&nbsp; 现在我们可以回到这一节的主题线性/树形递归。性/树形递归这个其实很好理解，就像sum和<span><span>sum_iter这样的程序的计算步骤是随参数arr而线性增长的，这种过程就是<font color="#000000"><font color="#ff0000">线性递归</font>。线性递归还可以细分为<font color="#ff0000">线性递归计算过程</font>和<font color="#ff0000">线性迭代计算过程</font>的递归，分别对应sum和</font></span></span><span><span>sum_iter。关于树形递归我就不多说了，可以很容易地联想到Tree这种结构。<font color="#ff0000">树形递归</font>的也是先展开后收缩的，只不过它的展开后的</span></span>求值过程是一棵树。这个不难联想到实际情况，例如自己写程序求某个目录下面的所有文件数或查找某个文件。但是这里有一点必须要注意。树形递归的效率比线性递归低得多。<br />
例如，求fibonacci数<br />
<div class="code_title">ruby 代码</div>
<div class="dp-highlighter">
<ol class="dp-rb" start="1">
    <li class="alt"><span><span class="keyword">def</span><span>&nbsp;fib(n)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;n&nbsp;==&nbsp;0&nbsp;:&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="keyword">elsif</span><span>&nbsp;n&nbsp;==&nbsp;1&nbsp;:&nbsp;1&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;fib(n-2)&nbsp;+&nbsp;fib(n-1)&nbsp;&nbsp;</span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span><span class="keyword">def</span><span>&nbsp;fib_iter(n,&nbsp;a&nbsp;=&nbsp;1,&nbsp;b&nbsp;=&nbsp;0)&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;<span class="keyword">if</span><span>&nbsp;n&nbsp;==&nbsp;0&nbsp;:&nbsp;a&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="keyword">else</span><span>&nbsp;&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;fib_iter(n&nbsp;-&nbsp;1,&nbsp;a&nbsp;+&nbsp;b,&nbsp;a)&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;<span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span><span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
</ol>
</div>
<br />
这是在我机器上运行求fib(10)的结果，当求fib(100)的时候，已经慢得让我无法忍受了。<br />
<div class="code_title">ruby 代码</div>
<div class="dp-highlighter">
<ol class="dp-rb" start="1">
    <li class="alt"><span><span>require&nbsp;'benchmark'&nbsp;&nbsp;</span></span></li>
    <li class=""><span>include&nbsp;Benchmark&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;</span></li>
    <li class=""><span>bmbm(12)&nbsp;<span class="keyword">do</span><span>&nbsp;</span><span class="variable">|x</span><span>|&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span>&nbsp;&nbsp;x.report(<span class="string">&quot;fib&quot;</span><span>)&nbsp;{&nbsp;1000.times&nbsp;{&nbsp;fib(10)&nbsp;}&nbsp;}&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;x.report(<span class="string">&quot;fib_iter&quot;</span><span>)&nbsp;{&nbsp;1000.times&nbsp;{&nbsp;fib_iter(10)&nbsp;}&nbsp;}&nbsp;&nbsp;</span></span></li>
    <li class="alt"><span><span class="keyword">end</span><span>&nbsp;&nbsp;</span></span></li>
    <li class=""><span>&nbsp;&nbsp;</span></li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;system&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;total&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;real&nbsp;&nbsp;</span></li>
    <li class=""><span>fib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.265000&nbsp;&nbsp;&nbsp;0.000000&nbsp;&nbsp;&nbsp;0.265000&nbsp;(&nbsp;&nbsp;0.266000)&nbsp;&nbsp;</span></li>
    <li class="alt"><span>fib_iter&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0.016000&nbsp;&nbsp;&nbsp;0.000000&nbsp;&nbsp;&nbsp;0.016000&nbsp;(&nbsp;&nbsp;0.016000)&nbsp;&nbsp;</span></li>
</ol>
</div>
<br />
&nbsp;&nbsp;&nbsp; 造 成这么大的差异的原因很大一部分是因为重复计算，例如求fib(10)的时候会求解fib(9) + fib(8)，然后求解fib(9)的时候仍然会再次求解fib(8)。当然这里有不少方法来提高树形递归的效率，但是其相对于线性递归的效率低下也是不 争的事实。这并不表明树形递归无用，在有些场合尤其是层次性数据的时候，非常有效。应为这种特殊场合比较难用线性递归或循环来处理，你需要懂懂脑子才能 （也许就想不出）办法把树形递归转换为线性递归或者循环处理。这里又不得不提性能，虽然我极力回避这个问题，但性能终究是一个问题。它使得你的程序运行的不那么好！<br />
<span></span>
          <br/>
          <span style="color:red;">
            <a href="http://joard.javaeye.com/blog/96491#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 01 Jul 2007 20:59:00 +0800</pubDate>
        <link>http://joard.javaeye.com/blog/96491</link>
        <guid>http://joard.javaeye.com/blog/96491</guid>
      </item>
  </channel>
</rss>