`
RednaxelaFX
  • 浏览: 3015223 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

Fibonacci数列的一种经典递归实现

    博客分类:
  • C#
阅读更多
刚才.NET课程期末考试,正好最后一题考的是递归实现Fibonacci数列.顺便就把代码打出来发在这里.
(虽然没什么技术含量 )

主要特性就是使用buffer将先前已经计算过的Fibonacci数列的值保存下来,减少递归时的重复计算开销.C#没直接的lazy evaluation,这种采取buffer的策略应该是不错的选择吧.
另外,实现了IEnumerable<T>和IEnumerable接口,方便遍历Fibonacci对象当前已经缓存了的值.
由于该数列采用int表示,在下标超过46(包括)时就会溢出,所以在检查下标后会抛异常,使用时需要注意.

using System;
using System.Collections.Generic;

namespace TestFibonacci
{
    class Program
    {
        /// <summary>
        /// Demo program.
        /// </summary>
        /// <param name="args"></param>
        static void Main( string[ ] args ) {
            // create a new Fibonacci instance
            Fibonacci fib = new Fibonacci( );

            // demonstrate the implementation of IEnumerator
            foreach ( int i in fib ) {
                Console.WriteLine( i );
            }

            // demostrate the implementation of indexer
            for ( int i = 10; i < 46; i++ ) {
                Console.WriteLine( fib[ i ] );
            }
        }
    }

    /// <summary>
    /// A class that calculates the Fibonacci sequence
    /// and buffers previously calculated values.
    /// The Fibonacci sequence described here starts
    /// from index 0 with a value of 1.
    /// Because the return value is represented in an int,
    /// this class does not support indexes larger than 46.
    /// </summary>
    public class Fibonacci : IEnumerator<int>
    {
        #region Fibonacci Constructors

        /// <summary>
        /// Default constructor. Buffer length defaults to 10.
        /// </summary>
        public Fibonacci( ) : this( 10 ) { }

        /// <summary>
        /// Create an Fibonacci instance with specified buffer length.
        /// </summary>
        /// <param name="initLength"></param>
        public Fibonacci( int initLength ) {
            this.buffer = new List<int>( );
            this.buffer.Add( 1 );
            this.buffer.Add( 1 );
            InitializeBuffer( initLength );
        }

        #endregion

        #region Fibonacci Member Methods

        /// <summary>
        /// Initialize the buffer of Fibonacci sequence.
        /// </summary>
        /// <param name="length">Length of buffer.
        /// Cannot exceed 46 or an OverflowException will be thrown</param>
        public void InitializeBuffer( int length ) {
            if ( length <= this.buffer.Count ) return;
            if ( length > 46 )
                throw new OverflowException(
                    string.Format( "index {0} will cause int to overflow",
                    ( length - 1 ).ToString( ) ) );

            Calculate( length - 1 );
        }

        /// <summary>
        /// Recursively calculate the Fibonacci sequence.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private int Calculate( int index ) {
            if ( index >= this.buffer.Count ) {
                int current = Calculate( index - 1 ) + Calculate( index - 2 );
                this.buffer.Add( current );
            }
            return this.buffer[ index ];
        }

        public IEnumerator<int> GetEnumerator( ) {
            return this;
        }

        #endregion

        #region Fibonacci Member Properties

        /// <summary>
        /// Read-only property for retrieving the
        /// Fibonacci sequence at specified index.
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public int this[ int index ] {
            get {
                InitializeBuffer( index + 1 );
                return this.buffer[ index ];
            }
        }

        #endregion

        #region Fibonacci Member Fields

        /// <summary>
        /// Buffers previously calculated values.
        /// </summary>
        private List<int> buffer;

        #endregion

        #region IEnumerator<int> Members

        /// <summary>
        /// Current enumerator cursor position.
        /// </summary>
        private int position = -1;

        public int Current {
            get {
                try {
                    return this.buffer[ position ];
                } catch ( IndexOutOfRangeException ) {
                    throw new InvalidOperationException( );
                }
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose( ) {
            // do nothing because there's nothing to release
        }

        #endregion

        #region IEnumerator Members

        object System.Collections.IEnumerator.Current {
            get {
                return this.Current;
            }
        }

        public bool MoveNext( ) {
            this.position++;
            return ( position < this.buffer.Count );
        }

        public void Reset( ) {
            this.position = -1;
        }

        #endregion
    }
}
分享到:
评论
3 楼 lwwin 2008-06-06  
yield 出现太多了…… C#表示什么?
2 楼 RednaxelaFX 2008-05-22  
顺带,上面这generator版本编译出来的东西是这样的:
(via Lutz Roeder's .NET Reflector)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;

public class FibonacciGenerator {
    public static IEnumerable<int> Generate(int ord) {
        <Generate>d__0 d__ = new <Generate>d__0(-2);
        d__.<>3__ord = ord;
        return d__;
    }

    [CompilerGenerated]
    private sealed class <Generate>d__0 : IEnumerable<int>, IEnumerable, IEnumerator<int>, IEnumerator, IDisposable {
        private int <>1__state;
        private int <>2__current;
        public int <>3__ord;
        private int <>l__initialThreadId;
        public int <current>5__5;
        public int <first>5__1;
        public int <i>5__4;
        public int <maxord>5__3;
        public int <second>5__2;
        public int ord;

        [DebuggerHidden]
        public <Generate>d__0(int <>1__state) {
            this.<>1__state = <>1__state;
            this.<>l__initialThreadId = Thread.CurrentThread.ManagedThreadId;
        }

        private bool MoveNext() {
            switch (this.<>1__state) {
                case 0:
                    this.<>1__state = -1;
                    this.<first>5__1 = 1;
                    this.<second>5__2 = 1;
                    this.<maxord>5__3 = (this.ord < 0x2e) ? this.ord : 0x2e;
                    this.<i>5__4 = 0;
                    while (this.<i>5__4 < this.<maxord>5__3) {
                        this.<current>5__5 = this.<first>5__1 + this.<second>5__2;
                        this.<>2__current = this.<first>5__1;
                        this.<>1__state = 1;
                        return true;
                    Label_0084:
                        this.<>1__state = -1;
                        this.<first>5__1 = this.<second>5__2;
                        this.<second>5__2 = this.<current>5__5;
                        this.<i>5__4++;
                    }
                    break;

                case 1:
                    goto Label_0084;
            }
            return false;
        }

        [DebuggerHidden]
        IEnumerator<int> IEnumerable<int>.GetEnumerator() {
            FibonacciGenerator.<Generate>d__0 d__;
            if ((Thread.CurrentThread.ManagedThreadId == this.<>l__initialThreadId) && (this.<>1__state == -2)) {
                this.<>1__state = 0;
                d__ = this;
            } else {
                d__ = new FibonacciGenerator.<Generate>d__0(0);
            }
            d__.ord = this.<>3__ord;
            return d__;
        }

        [DebuggerHidden]
        IEnumerator IEnumerable.GetEnumerator() {
            return this.System.Collections.Generic.IEnumerable<System.Int32>.GetEnumerator();
        }

        [DebuggerHidden]
        void IEnumerator.Reset() {
            throw new NotSupportedException();
        }

        void IDisposable.Dispose() { }

        int IEnumerator<int>.Current {
            [DebuggerHidden]
            get { return this.<>2__current; }
        }

        object IEnumerator.Current {
            [DebuggerHidden]
            get { return this.<>2__current; }
        }
    }
}
1 楼 RednaxelaFX 2008-05-20  
明天有同学考.NET,又让我翻出这题。想了想,要让他们能记住的话这么长的代码肯定不行……于是给他们写了这个短版本:
using System;
using System.Collections.Generic;

public class FibonacciGenerator {
    public static IEnumerable<int> Generate(int ord) {
        int first = 1;
        int second = 1;
        int maxord = (ord < 46)? ord : 46;
        for (int i = 0; i < maxord; ++i) {
            int current = first + second;
            yield return first;
            first = second;
            second = current;
        }
    }
}

sealed class Program {
    static void Main(string[] args) {
        int n = 10;
        foreach (int i in FibonacciGenerator.Generate(n)) {
            Console.WriteLine(i);
        }
    }
}

哦哦C#的generator真是太有爱了 T T

相关推荐

    python斐波那契数列第n项.docx

    递归方法 def fibonacci(n): if n &lt;= 1: return n else: return fibonacci(n-1) + fibonacci(n-2) n = int(input("请输入要计算的斐波那契数列的项数:")) print("斐波那契数列的第", n, "项为:", fibonacci(n)) 2...

    斐波那契数列的三种算法.doc

    斐波那契数列的三种算法,算法一:递归 #include #include long int fibo(int n) { if(n==0) return 0; if(n==1) return 1; return fibo(n-1)+fibo(n-2); } void main() {

    Java经典例题教程:计算斐波那契数列

    我们将涵盖循环和递归两种不同的方法,以帮助您理解常用的编程知识点,并逐步解释代码的思路和逻辑斐波那契数列是一个常见的数学序列,在计算机科学和编程中经常用到。本教程将向您展示如何使用Java编写代码来计算...

    java实现斐波那契数列的3种方法

    主要介绍了java实现斐波那契数列的3种方法,有需要的朋友可以参考一下

    斐波那契数列python实现

    使用python的方法实现斐波那契数列,主要使用两种方法,一种是使用递归方式来实现,另一种是使用的动态规划的算法实现,两种方法递归算法主要是时间复杂度高,但是效率较低,而对于动态规划算法实现方式,降低了时间...

    如何使用Python实现斐波那契数列

    斐波那契数列(Fibonacci)最早由印度数学家Gopala提出,而第一个真正研究斐波那契数列的是意大利数学家 Leonardo Fibonacci,斐波那契数列的定义很简单,用数学函数可表示为: 数列从0和1开始,之后的数由前两个数...

    C#实现斐波那契数列的几种方法整理

    斐波那契数列,又称黄金分割数列,指的是这样一个数列:1、1、2、3、5、8、13、21、……想必看到这个数列大家很容易的就推算出来后面好几项的值,那么到底有什么规律,简单说,就是前两项的和是第三项的值,用递归...

    求斐波那契(Fibonacci)数列通项的七种实现方法

    一:递归实现使用公式f[n]=f[n-1]+f[n-2],依次递归计算,递归结束条件是f[1]=1,f[2]=1。二:数组实现空间复杂度和时间复杂度都是0(n),效率一般,比递归来得快。三:vector实现时间复杂度是0(n),时间复杂度是0(1)...

    兔子问题--斐波那契数列--递归--面向过程编程--面向对象编程--2种

    题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为...1. 递归,面向过程编程,简单直接 2. 面向对象编程,别人写的,

    c语言斐波那契数列

    使用递归和非递归的算法,分别计算斐波那契数列,并利用系统时间函数对每一个n值的两种计算方法计时

    python基础编程:详解python使用递归、尾递归、循环三种方式实现斐波那契数列

    本篇文章主要介绍了python使用递归、尾递归、循环三种方式实现斐波那契数列,非常具有实用价值,需要的朋友可以参考下 在最开始的时候所有的斐波那契代码都是使用递归的方式来写的,递归有很多的缺点,执行效率低下...

    用Python实现斐波那契(Fibonacci)函数

    Fibonacci斐波那契数列,很简单,就是一个递归嘛,学任何编程语言可能都会做一下这个。 最近在玩Python,在粗略的看了一下Learning Python和Core Python之后,偶然发现网上有个帖子Python程序员的进化写的很有意思。...

    利用Python实现斐波那契数列的方法实例

    今天我们来使用Python实现递归算法求指定位数的斐波那契数列 首先我们得知道斐波那契数列是什么? 斐波那契数列又叫兔子数列 斐波那契数列就是一个数列从第三项开始第三项的值是第一项和第二项的和依次类推 其次...

    详解python使用递归、尾递归、循环三种方式实现斐波那契数列

    在最开始的时候所有的斐波那契代码都是使用递归的方式来写的,递归有很多的缺点,执行效率低下,浪费资源,还有可能会造成栈溢出,而递归的程序的优点也是很明显的,就是结构层次很清晰,易于理解 可以使用循环的...

    python-递归算法.docx

    斐波那契数列是一个非常经典的数列,它的定义如下: F(0) = 0 F(1) = 1 F(n) = F(n-1) + F(n-2) (n&gt;=2) python-递归算法全文共3页,当前为第1页。 使用递归算法来计算斐波那契数列的代码如下: python-递归算法全文...

    Go语言实现Fibonacci数列的方法

    第一种,使用递归: 代码如下:func fibonacci(a int) int {   if a == 1 || a == 2 {   return 1   }   return fibonacci(a-1) + fibonacci(a-2)  } 第二种,不使用递归: 代码如下:func fibonacci_...

    python斐波那契数列的计算方法

    计算斐波那契数列。具体什么是斐波那契数列,那就是0,1,1,2,3,5,8,13,21,34,55,89,144,233。 要求: 时间复杂度尽可能少 分析: 给出了三种方法: 方法1:递归的方法,在这里空间复杂度非常大。...

    组合数学实验 Fibonacci数列 二项式系数的加法求解

    实验一、Fibonacci数非递归解 Fibonacci数列 的定义如下: 请用递归方法和非递归方法求解该问题,各编写一个函数,要求函数接受 的值,返回 的值。两个程序实现后,分别求 的情况,对比两个程序的执行时间,然后...

    JavaScript的递归之递归与循环示例介绍

    任何一个循环的代码都可以用递归改写,实现相同的功能;反之亦然。在不失去其普遍性的前提下,可以把循环和递归分别用下列伪代码概括。 伪代码格式说明:循环采用while形式;变量不加定义;赋值用:=;条件表达式和...

    【Python学习-递归-斐波那契数列】【剑指offer】之跳台阶

    【Python学习-递归-斐波那契数列】【剑指offer】之跳台阶题目分析代码变态跳台阶分析代码矩形覆盖分析代码 题目 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序...

Global site tag (gtag.js) - Google Analytics