数据结构基础--复杂度计算

一、算法的复杂度

算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。因此衡量一个算法的好坏,一般是从时间和空间两个维度来衡量的,即时间复杂度和空间复杂度。


时间复杂度主要衡量一个算法的运行快慢,而空间复杂度主要衡量一个算法运行所需要的额外空间。在计算机发展的早期,计算机的存储容呈很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。
 

二、时间复杂度

时间复杂度的定义:在计算机科学中,(算法的时间复杂度是一个函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算田来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。
 

大O表示法:算法的时间复杂度通常用大O符号表述,定义为T[n] = O(f(n))。称函数T(n)以f(n)为界或者称T(n)受限于f(n)。 如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n)。T(n)称为这一算法的“时间复杂度”。当输入量n逐渐加大时,时间复杂度的极限情形称为算法的“渐近时间复杂度”。

推导大O阶方法:

1.用常数1取代运行时间中所有的加法常数

2.在修改后的运行次数函数中,只保留最高阶项,其他项对结果的影响不大

3.如果最高阶项存在,且不是1,则去除与这个项相乘的常数,也就是不要系数

 

 

 算法的时间复杂度存在最好、平均和最坏情况,这里用在长度为N的数组中搜索x举例

最好情况:任意输入规模的最少运行次数(上界),1次找到

平均情况:任意输入规模的期望运行次数,2/N次找到

最坏情况:任意输入规模的最大运行次数(下界),N次找到

假设数组为acdhegfs。如果逐个遍历,查找a一次就能找到,查找h四次就能找到,查找s八次才能找到; 

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
 void Swap(int* a,int* b)
 {
     int c=*a;
     *a=*b;
     *b=c;
 }
int* sortArray(int* nums, int numsSize, int* returnSize)
{
    for(int i=0;i<numsSize;i++)
    {
        int if_finish=0;
        for(int j=1;j<numsSize-i;j++)
        {
            if(nums[j-1]>nums[j])
            {
                Swap(&nums[j-1],&nums[j]);
                if_finish=1;
            }
        }
        if(if_finish==0)
        {
            break;
        }
    }
    *returnSize=numsSize;
    return nums;
}

对于如上的冒泡排序,第一个元素要对比N-1次,第二个元素对比N-2次,以此类推,第k个元素对比N-k次,最后一个元素对比1次。将所有的对比次数求和,等差数列求和为N*(N-1)/2,所以时间复杂度为O(N^2) 

如上图所示的二分查找法,对有序的数组进行查找,假设数组是递增的,每次查找,查找区间缩小一半,直到最后只剩一个数字,也就是查找的数字。假设查找m次,那么N=1*2*2*2*2……,N=2^m次,m=log2(N),2为底数 

递归时间复杂度:每次递归调用执行次数累加

如上图所示的阶乘, Fac(N)+Fac(N-1)+Fac(N-2)+……+Fac(1),总共是N个递归函数调用,所以时间复杂度为O(N)

如上图所示的阶乘内部带循环, Fac(N)+Fac(N-1)+Fac(N-2)+……+Fac(1),总共是N个递归函数调用,第一次调用内部循环N次,第二次调用内部循环N-1次,第k次调用内部循环N-k次,第N次调用内部循环1次。所以是等差数列求和,N+(N-1)+(N-2)+(N-3)+……+1。也就是N*(N-1)/2。时间复杂度为O(N^2)

如上图所示的斐波那契数列 ,总共调用了2^0+2^1+2^2+……+2^(N-2)=2^(N-1)-1,等比数列求和,所以时间复杂度为O(2^N)

三、空间复杂度

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度
空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟实践复杂度类似,也使用大O渐进表示法。
注意:函数运行时所需要的栈空间(存储参数、局部变量、一些寄存器信息等)在编译期间已经确定好了,因此空间复杂度主要通过函数在运行时候显式申请的额外空间来确定。

空间复杂度为O(1) 


冒泡排序的空间复杂度为O(1) 

阶乘的空间复杂度为O(N),因为每次调用都会开辟一块新的空间, Fac(N)+Fac(N-1)+Fac(N-2)+……+Fac(1),总共是N个递归函数调用,所以空间复杂度为O(N)

如上图所示的斐波那契数列,用malloc开辟了n+1块大小为sizeof(long long)的空间,所以空间复杂度为O(N)

 递归的斐波那契数列,由于函数调用的栈帧不能无限创建,如果N过大程序会报错。空间可以重复利用,所以总共开辟了Fib(N)+Fib(N-1)+Fib(N-2)+……+Fib(1),总共开辟了N个空间,所以空间复杂度为O(N)

 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构与算法是计算机科学中非常重要的基础知识。数据结构是指在计算机中组织和存储数据的方式,而算法则是解决问题的步骤和方法。下面是关于数据结构与算法的基础知识: 1. 数据结构学习的内容: - 数据结构的学习主要包括如何用程序代码将现实世界的问题信息化,以及如何用计算机高效地处理这些信息并创造高价值。 - 数据结构学习的目标是掌握各种数据结构的特点、操作和应用场景,以便在解决实际问题时能够选择合适的数据结构。 2. 数据的定义: - 数据是对客观事物的符号表示,是计算机程序的基本元素。 - 数据可以是数字、字符、字符串、图像等各种形式。 3. 程序 = 数据结构 + 算法: - 程序由数据结构和算法组成,数据结构用于组织和存储数据,算法用于处理数据。 - 数据结构和算法是程序设计的核心内容,对程序的效率和质量有着重要影响。 4. 算法的特性: - 有穷性:算法必须在有限的步骤内结束。 - 确定性:算法中的每条指令都有确切的含义,对于相同的输入只能得到相同的输出。 - 可行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。 5. “好”算法的特质: - 正确性:算法应该能够正确地解决问题。 - 可读性:算法应具有良好的可读性,以帮助人们理解。 - 健壮性:算法能够适当地处理非法输入,而不会产生奇怪的输出结果。 - 高效率与低存储需求:算法执行速度快,时间复杂度低;算法不占用过多的内存,空间复杂度低。 6. 算法效率的度量: - 时间复杂度:用来估计算法的时间开销与问题规模的关系。 - 空间复杂度:用来估计算法的存储空间需求与问题规模的关系。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值