算法与数据结构【C语言版】———1.时间复杂度与空间复杂度

本文介绍了算法效率的两个关键指标——时间复杂度和空间复杂度。时间复杂度衡量算法执行时间与数据规模的关系,通过大O表示法进行分析,例如二分查找的时间复杂度为O(log₂N)。空间复杂度则关注算法运行时所需内存。以斐波那契数列的递归实现为例,其时间复杂度为O(2^N),展示了递归可能导致的高时间复杂度。理解这些概念有助于优化算法设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

算法效率

什么是时间复杂度?

时间复杂度的计算

时间复杂度做悲观预期

什么是空间复杂度?



算法效率

如何衡量一个算法的好坏呢?是否越简洁就是越好的算法呢?我们举如下例子:

long long Fib(int n)
{
    if(n<3)
        return 1;
    return Fib(n-1)+Fib(n-2); 
}

这是斐波那契数列递归方式的实现, 代码虽然简洁,但是效率一定高吗?并不是这样。这里我们的算法效率一般是从时间和空间两个维度来衡量的。即时间复杂度和空间复杂度。

什么是时间复杂度?

在计算机科学中,算法的时间复杂度是一个函数,描述算法的执行时间与数据规模之间的增长关系,用来衡量算法运行的快慢。从理论上讲,是不能算出来具体时间的,只有将程序上机运行,才能知道,而且不同计算机的计算能力也会是使得具体时间不同。所以,我们用时间复杂度的分析方式来解决,一个算法花费的时间与其执行次数成正比,因此,算法中的基本操作的执行次数,为算法的时间复杂度。

时间复杂度的计算

即找到某条基本语句与问题规模N之间的数学表达式,就是算法的时间复杂度。

例如,求下面代码中Fun函数中number++语句共执行了多少次?

void Fun(int N)
{
    int number=0;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<N;j++)
        {
            number++;
        }
    }
   for(int k=0;k<2*N;k++)
    {
        number++;
    }
    int M=20;
    while(M--)
    {
        number++:
    } 
    printf("%d",number):
}

由分析可知,时间复杂度函数F(N)=N^2+2*N+20.

  • N=10              F(N)=140
  • N=100            F(N)=10220
  • N=1000          F(N)=1002020
  • ··········

N值越大,后两项对结果影响越小。实际上并不一定要计算精确的执行次数,这里我们用到大O渐进表示法。即表示为 O(N^2).(即保留原函数中影响最大的一项)

下面是大O表示法随N的增长曲线

 几种常见时间复杂度函数的大O表示法:

了解时间复杂度的计算之后,看下面一个例子

 如何计算二分查找法查找x的时间复杂度?


int BinarySearch(int *a, int n, int x )
{
    assert(a);
    int left = 0;
    int right = n;
    while(left < right)
    {    
        int mid = left + ((right-left)>>1);
        if(a[mid] < x)
            left = a[mid] + 1;
        else if(a[mid] > x)
            right = a[mid];
        else
            return a[mid];
    }
    return 0;
}

 由分析可知,x正好位于数组中间时,此时只需要执行一次就可以查找出x,这是最好的情况,时间复杂度为O(1);当数组中查找不到x或x在数组最边上时,此时需要执行很多次循环,时间复杂度为最坏的境况,每执行一次N的值都减半,因此时间复杂度为O(log₂N);这里就需要对时间复杂度做悲观预期。

时间复杂度做悲观预期

一般情况下,当一个算法随着输入不同,时间复杂度不同时,我们要考虑该算法的最坏执行情况,即对时间复杂度做悲观预期,来表示该算法的时间复杂度。

最后回到最开始的问题,来看看斐波那契数列的递归实现方式的时间复杂度是怎样的?

用图解说明

 可以看出,每次调用都会有两个新的分支,即二叉树,时间复杂度表示为O(2^N)。当N=50时就已经是非常大的数了,时间复杂度很高,并不够高效。最好不使用递归方法实现斐波那契数列。

什么是空间复杂度?

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用储存空间大小的量度。

因为内存发展很快,现在的计算机内存空间很大,所以看程序占用了多大空间也没有意义,一般算变量的个数来表示空间复杂度,也用大O渐进表示法。但不同于时间的是,空间是可以重复利用的,用过的空间可以归还后再次开辟使用,不像时间是线性轴的。

例如:计算斐波那契数列函数的空间复杂度。

long long *Fib(size_t n)
{
    if(n==0)
        return NULL;

    long long *fibarray = (long long*)malloc(n+1*sizeof(long long));
    fibarray[0] = 0;
    fibarray[1] = 1;
    for(int i = 2;i <= n;++i)
    {
        fibarray[i] = fibarry[i-1] + fibarry[i -2];
    }
    return fibarray;
}

由分析可知,先递归第一次调用时开辟N个空间,之后每一次递归都可以重复使用第一次开辟的空间,所以空间复杂度为O(N)

 最后,这是对自己每天学习的一个小记录,每一次知识的掌握都离不开勤奋的练习,加油加油!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值