斐波那契数列算法的优化设计

原创 2015年07月06日 16:54:15
  1. 基本概念

    • 数据:信息载体,被计算机识别处理的集合符号
    • 数据元素:数据基本单位
    • 数据对象:具有相同性质的数据元素集合
    • 数据类型:一个值得集合与定义在此集合上的一组操作总称
    • 抽象数据类型:数据结构+定义与此的一组操作
    • 数据结构:相互之间存在一种或多种关系的数据关系集合
  2. 数据结构三要素

    • 逻辑结构:分为线性结构和非线性结构。如下图:

数据机构逻辑分类图

  • 线性表:元素之间只存在一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。
  • 线性表有两种存储方式,一种是顺序存储结构,另一种是链式存储结构。

  • 集合:同属于一个集合

  • 属性结构:元素存在一对多的关系
  • 图状结构或网状结构:元素存在多对多关系

    • 存储结构:

      顺序存储:相邻元素存储在物理位置上,元素之间关系由存储单元表示。

      优点:可以实现随机存取,元素占用最少空间

      缺点:只能使用相邻一块存储单元,可能产生较多外部碎片

      链式存储:逻辑上相邻元素存储在物理位置上也相邻存储单元里,元素之间由存储单元邻接关系体现。

      优点:充分利用所有存储单元;

      缺点:每个元素因存储指针而占用额外的存储空间,只能实现顺序存取

      索引存储:建立附加索引表;

      优点:检索速度快

      缺点:增加的索引表,占用过多存储空间;修改时,也会话费很多时间
      散列存储:根据元素关键字直接计算出该元素的存储地址,称为Hash存储

    优点:检索,增加和删除结点操作更快;

    缺点:如果散列函数不好则会出现元素存储单元的冲突,解决冲突需要增加时间和空间开销

3.算法的特点
有穷性、确定性、可行性、输入、输出,其含义,你懂得,无需我多言

4.算法效率的度量

  • 时间复杂度

    一个语句频度在该语句在算法中被重复执行次数,所有语句频度之和,记作:T(n) 是算法问题规模N的函数

  • 空间复杂度

    S(n),定义为算法所耗费的存储空间,是问题规模N的函数

思维拓展
1.对于两种不同的数据结构,逻辑结构或物理结构一定不相同吗?

两种不同的数据结构,他们的逻辑结构和物理结构完全有可能相同。比如二叉树和二叉排序树,二叉排序树可以采取二叉树的逻辑表示和存储方式,前者通常用来表示层次关系,而后者通常用来排序和查找。虽然运算都有建立树,插入结点,删除结点和查找结点等,但是对于二叉树和二叉排序树,这些运算定义是不同的,以查找为例,二叉树时间复杂度是O(n),而二叉排序树是O(log2n)

经典题目2:写一个函数,输入n,其斐波那契数列的第n项。

方法1:使用递归解,时间复杂度是n的指数级别

#include<iostream>
#include<stdlib.h>
using namespace std;

int Fibonacci(int n)
{
    if(n<=0)
        return 0;
    if(n==1)
        return 1;
    return Fibonacci(n-1)+Fibonacci(n-2);
}

void main()
{
    int f=Fibonacci(10);
    cout<<f<<endl;
    system("pause");
}

时间复杂度是n的指数级别,随着n的增大,以f(10)为例,f(10)=f(9)+f(8),f(9)=f(8)+f(7)。其中的f(8)就是重复计算的。

方法2:开辟一个长度为(n+1)的数组,时间复杂度为O(n),空间复杂度为O(n)

将这些计算出来的值保存在一个数组arry[n+1]上,这样计算斐波那契数列就相当于是一个填表的过程:

int Fibonacci(int n)
{
    if(n<=0)
        return 0;
    else if(n==1)
        return 1;
    else
    {
        //动态创建一个长度为(n+1)的数组
        int *arr=new int[n+1];
        arr[0]=0;
        arr[1]=1;
        for(int i=2;i<=n;i++)
        {
            arr[i]=arr[i-1]+arr[i-2];
        }
        int result=arr[n];

        delete [] arr;
        return result;
    }
}

注意点:

  1. 因为不知道要求的f(n)中的n有多大,因此不能事先开辟一个数组,需要动态创建数组。而动态数组与数组变量不同,动态分配的数组将一直存在,直到程序显式释放它为止。普通的数组变量,只要出了数组的作用于,其内存会自动释放。

  2. c++提供delete []表达式释放指针所指向的数组空间。delete []
    arry;该语句回收了arr所指向的数组,把相应的内存返回给自由存储区。在关键字delete和指针arr之间的方括号[]是必不可少的:它告诉编译器该指针指向的是自由存储区中的数组,而非单个对象。delete
    arry只释放了arr指针所指向的内存地址,理论上来说会少释放了内存空间,从而产生内存泄露。

    方法3:优化方法2,空间复杂度为O(1),时间复杂度为O(n)

int Fibonacci(int n)
{
    if(n<=0)
        return 0;
    else if(n==1)
        return 1;

    else
    {
        //当n>=2时,初始化pre=f(0)=0,post=f(1)=1,f(n)=0;
        int pre=0;
        int post=1;
        int fn=0;
        //采用循环计算斐波那契数列,通过两个临时变量pre和post保存中间结果,避免重复计算
        for(int i=2;i<=n;i++)
        {
            fn=pre+post;//fn等于其前面两个元素值的和
            //然后让pre和post分别直线他们后面的元素。
            pre=post;
            post=fn;
        }
        return fn;
    }
}

Fibonacci(斐波纳契)数列各种优化解法

Fibonacci数列:   描述了动物繁殖数量、植物花序变化等自然规律。作为一个经典的数学问题,Fibonacci数列常作为例子出现在程序设计、数据结构与算法等多个相关学科中。  下面简单地分析一...
  • lmyclever
  • lmyclever
  • 2011年04月17日 08:55
  • 4359

求菲波那切数列数列第n项三种方法小结

求菲波那切数列数列第n项三种方法小结---递归&滚动数组&数学通项公式
  • u010251278
  • u010251278
  • 2016年03月07日 21:02
  • 1625

斐波那契数(C/C++,Scheme)

一、背景斐波那契数的定义: f0=0 f_0 = 0 f1=1 f_1 = 1 fi=fi−1+fi−2(i>1) f_i = f_{i-1}+f_{i-2} (i > 1) 二、分析我引...
  • NoMasp
  • NoMasp
  • 2015年05月25日 21:50
  • 2682

[51Nod算法马拉松14 F] 斐波那契树

官方题解用树上倍增做的…转移感觉超级厉害也超级麻烦我没有看懂 QAQ 所以来分享一下点分 + 矩阵的做法… 分治跟 SCOI 2016 D2T3 其实挺像的就不多说了 有什么细节问题可以看代码#inc...
  • visit_world
  • visit_world
  • 2016年05月30日 10:03
  • 1240

菲波那契数 ----C++

第一种方法,借助数组。#include #include using namespace std; int main(int argc, char* argv[]) { int n; ...
  • a1b2c3d4123456
  • a1b2c3d4123456
  • 2015年12月26日 14:31
  • 485

java实现斐波拉契数列

package algorithm.cxg.Fibonacci; import java.util.Scanner; /** * 实现斐波拉切函数 * 斐波拉切数列: * 由0和1开始,之后...
  • captian_900331
  • captian_900331
  • 2015年11月04日 12:42
  • 1239

oj1610: 菲波那契数

问题描述:菲波那契(fibonacci)数(简称菲氏数)定义为: f(0) = 0; f(1) = 1; f(n) = f(n-1) + f(n-2). n>1的整数如果写出菲氏数列,则应该是: 0 ...
  • qq_36203090
  • qq_36203090
  • 2017年02月17日 14:56
  • 127

斐波那契数列使用递归的运行时间分析

在这学期(大三上)去“蹭”了一次校招面试题,编程题中就有一道关于斐波那契数列的编程问题。如果不选择递归求解,需要说明原因。当时还没怎么接触算法这方面的知识(笔者非科班),关于什么运行时间分析、空间复杂...
  • ZeroOnet
  • ZeroOnet
  • 2016年11月17日 11:19
  • 1175

斐波那契数数列

在一张纸上并排画 11 个小方格。叫你的好朋友背对着你(确保你看不到他在纸上写什么),在前两个方格中随便填两个 1 到 10 之间的数。从第三个方格开始,在每个方格里填入前两个方格里的数之和。让你的朋...
  • qq_21792169
  • qq_21792169
  • 2016年06月08日 22:57
  • 17830

斐波那契数列的递归与循环的算法实现

前半篇转载地址:http://blog.csdn.net/woshisap/article/details/7566946 斐波那契数列,但凡学过编程的童鞋们应该都懂,背景就不介绍了(就是大兔...
  • Micro_Ryan
  • Micro_Ryan
  • 2015年08月22日 09:31
  • 4380
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:斐波那契数列算法的优化设计
举报原因:
原因补充:

(最多只允许输入30个字)