C#斐波那契数列的各种算法【递归、循环、数组】比较

斐波那契数列,就是整数: 第三项 等于前两项之和.A(n)=A(n-2)+A(n-1).

例如:1,1,2,3,5,8,13,21,34,55,....

现在使用四种方式:

一、递归

二、For循环【使用临时变量】

三、For循环【无临时变量】

四、使用数组作为临时仓库

测试四种算法的性能。以及计算出从第几项开始,超过Int32的最大值

新建控制台应用程序FibonacciSequenceDemo

测试源程序如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FibonacciSequenceDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.SetWindowSize(120, 30);
            Task taskRecursion = Task.Run(() => { AlgorithmTimespan(GetFibonacciRecursion, nameof(GetFibonacciRecursion)); });
            Task taskFor = Task.Run(() => { AlgorithmTimespan(GetFibonacciFor, nameof(GetFibonacciFor)); });
            Task taskForNoTemp = Task.Run(() => { AlgorithmTimespan(GetFibonacciForNoTemp, nameof(GetFibonacciForNoTemp)); });
            Task taskArray = Task.Run(() => { AlgorithmTimespan(GetFibonacciArray, nameof(GetFibonacciArray)); });
            Task.WaitAll(taskRecursion, taskFor, taskForNoTemp, taskArray);
            Console.WriteLine("-------------测试多次调用斐波那契数列方法的用时【获取第一个大于Int32的最大值】------------------");
            taskRecursion = Task.Run(() => { AlgorithmTimespanMultiple(GetFibonacciRecursion, nameof(GetFibonacciRecursion)); });
            taskFor = Task.Run(() => { AlgorithmTimespanMultiple(GetFibonacciFor, nameof(GetFibonacciFor)); });
            taskForNoTemp = Task.Run(() => { AlgorithmTimespanMultiple(GetFibonacciForNoTemp, nameof(GetFibonacciForNoTemp)); });
            taskArray = Task.Run(() => { AlgorithmTimespanMultiple(GetFibonacciArray, nameof(GetFibonacciArray)); });
            Task.WaitAll(taskRecursion, taskFor, taskForNoTemp, taskArray);
            Console.ReadLine();
        }

        /// <summary>
        /// 算法用时:单次
        /// </summary>
        /// <param name="FibonacciMethod"></param>
        /// <param name="methodName"></param>
        static void AlgorithmTimespan(Func<int, long> FibonacciMethod, string methodName)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            int nItem = 40;
            long number = FibonacciMethod(nItem);
            Console.WriteLine($"【{methodName.PadRight(26)}】,第【{nItem + 1}】项=【{number}】,用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");
        }

        /// <summary>
        /// 计算多次使用斐波那契函数的时间
        /// </summary>
        /// <param name="FibonacciMethod"></param>
        /// <param name="methodName"></param>
        static void AlgorithmTimespanMultiple(Func<int, long> FibonacciMethod, string methodName)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();
            long number;
            int nItem = GetIndexLargerMaxInt32(FibonacciMethod, out number);
            Console.WriteLine($"【{methodName.PadRight(26)}】,第【{nItem + 1}】项=【{number}】超过Int32的最大值,用时【{stopwatch.Elapsed.TotalMilliseconds}】ms");
        }

        /// <summary>
        /// 找出斐波那契数列的第几项超过Int32的最大值
        /// </summary>
        /// <param name="FibonacciMethod"></param>
        /// <returns></returns>
        static int GetIndexLargerMaxInt32(Func<int, long> FibonacciMethod, out long number)
        {
            int nItem = 0;
            number = 0;
            while (true)
            {
                number = FibonacciMethod(nItem);
                if (number >= Int32.MaxValue)
                {
                    break;
                }
                nItem++;
            }
            return nItem;
        } 

        /// <summary>
        /// 获取斐波那契数列的第N项,索引从0开始 使用递归
        /// </summary>
        /// <param name="nItem">索引:从0开始</param>
        /// <returns></returns>
        static long GetFibonacciRecursion(int nItem)
        {
            if (nItem <= 1)
            {
                return 1;
            }
            return GetFibonacciRecursion(nItem - 1) + GetFibonacciRecursion(nItem - 2);
        }

        /// <summary>
        /// 获取斐波那契数列的第N项,索引从0开始 使用For循环
        /// </summary>
        /// <param name="nItem">索引:从0开始</param>
        /// <returns></returns>
        static long GetFibonacciFor(int nItem)
        {
            long first = 1;
            long second = 1;
            for (int i = 1; i < nItem; i++)
            {
                long temp = first;
                first = first + second;
                second = temp;
            }
            return first;
        }

        /// <summary>
        /// 获取斐波那契数列的第N项,索引从0开始 使用For循环,不使用临时变量
        /// </summary>
        /// <param name="nItem"></param>
        /// <returns></returns>
        static long GetFibonacciForNoTemp(int nItem)
        {
            long first = 1;
            long second = 1;
            for (int i = 1; i < nItem; i++)
            {
                first = first + second;
                second = first - second;
            }
            return first;
        }

        /// <summary>
        /// 获取斐波那契数列的第N项,索引从0开始 使用数组仓库
        /// </summary>
        /// <param name="nItem">索引:从0开始</param>
        /// <returns></returns>
        static long GetFibonacciArray(int nItem)
        {
            long[] array = new long[nItem + 1];
            for (int i = 0; i < array.Length; i++)
            {
                if (i <= 1)
                {
                    array[i] = 1;
                }
                else
                {
                    array[i] = array[i - 1] + array[i - 2];
                }
            }
            return array[nItem];
        }
    }
}
 

运行效果如图:

我们发现:性能比较结果,依次为:

【for(无临时变量)】

【for(有临时变量)】

【数组仓库】

【递归】

这也是我们编程中经常提醒:尽量减少使用递归

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值