【数据结构与算法】算法的空间复杂度和时间复杂度的计算

一、什么是算法?
1、算法就是求解问题的一系列步骤的集合。
2、通常把具体存储结构上的操作实现步骤或过程称为算法。

二、算法的五个重要特性
有穷性: 对于任意一组合法的输入值,在执行有穷步骤之后一定能结束。
确定性:每条指令必须有确切的含义,不能有二义性。
可行性:算法中描述的操作都是用已经实现的基本运算组成。
输入:可以有零个或多个输入。
输出:一组与"输入"有确定关系的量值。有一个或多个输出,要有输出算法才有意义。

三、算法的设计准则
正确性:除了应该满足算法说明中写明的“功能”之外,应对各组典型的带有苛刻条件的输入数据得出正确的结果 。
健壮性:算法应对非法输入的数据作出恰当反映或进行相应处理,一般情况下,应向调用它的函数返回一个表示错误或错误性质的值。
可读性 :易于理解、实现和调试。
高效性(时空效率):执行时间短(时间效率)、占用存储空间少(空间效率)

算法占用的资源分别是CPU时间和内存空间,CPU时间就是时间性能,内存空间就是空间性能。

四、算法时间复杂度分析和计算

一个算法是由控制结构(顺序、分支和循环三种)和原操作(指固有数据类型的操作,如+、-、*、/、++和–等)构成的。算法执行时间取决于两者的综合效果。
一般用算法中语句被执行的次数(频度)来表示算法的时间效率。

算法时间性能分析方式:
事后分析统计
:编写算法相关或对应的程序,然后统计算法的执行时间。
但是这个有缺点,由于编写程序的语言不同、执行程序的环境不同等其他因素的影响,同样的算法执行的时间也有可能不同,所以不能用绝对的执行时间进行比较。

事前估算分析:
撇开上述编写程序的语言不同、执行程序的环境不同等因素,在编写程序前,依据统计方法对算法进行估算,认为算法的执行时间是问题规模n的函数。 
在这里插入图片描述
求出算法所有原操作的执行次数(也称为频度) ,它是问题规模n的函数,用T(n)表示。

为什么for控制结构那里是n+1次?
因为第n次时条件成立,for 继续执行,for执行第n+1次时,条件不成立,跳出循环,所以for语句多执行了一次。

由上可知:T(n) = 2n+3
T(n)是n数量级的,是时间频度(就是算法中语句执行的数次),不是时间复杂度O(n).

时间复杂度(全称是渐进时间复杂度,用大O表示):
忽略次要语句的执行次数,只对重要的语句(原操作)和执行最频繁的语句进行计数,同时对计算结果只取其最高次幂,且略去系数不写。也就是只求出T(n)的最高阶,忽略其低阶项和常系数,这样既可简化T(n)的计算,又能比较客观地反映出当n很大时算法的时间性能。
例如:T(n) = 2n+1 = O(n)、T(n) = 2n2+2n+2000 = O(n2).

int sum = 0;	//频度(执行次数)1次
void matrixadd(int n)
  {	
  	int i,j;	//频度(执行次数)1次
   	for (i=0; i<n; i++) 	//频度(执行次数)n+1次
   	{
   		for (j=0; j<n; j++)	//频度(执行次数)n(n+1)次
   		{
   			sum = i + j;	//频度(执行次数)n*n次
   		}
   	}   
  }

所有语句频度 T(n) = 2n2+2n+3
时间复杂度 O(n2)

各种时间复杂度
1、一个没有循环的算法的基本运算次数与问题规模n无关,记作O(1),也称作常数阶。
2、一个只有一重循环的算法的基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。
3、其余常用的还有平方阶O(n2)、立方阶O(n3)、对数阶O(log2n)、指数阶O(2n)等。
4、各种不同数量级对应的值存在着如下大小关系:
O(1)<O(log2n)<O(n)<O(n*log2n)<O(n2)<O(n3)<O(2n)<O(n!)

O(1)、O(n)、O(n2)这三个上面讲过啦,看看其他的:
O(log2n)

int i = 1;
while(i<n)
{
    i = i * 2;
}

每次乘以2都离n值近一点。
解:设循环x次之后,i 的值就大于 n 了,此时这个循环就退出了,
也就是说 2 的 x 次方大于或等于 n,由于n是上限,可以写成2的x次方等于n,
即 x = log2^n
也就是说当循环 log2^n 次以后,这个代码就结束了。
因此这个代码的时间复杂度为:O(log2n)

O(n*log2n)

for(j=1; j<n; j++)
{
    i = 1;
    while(i<n)
    {
        i = i * 2;
    }
}

n*log2n是log2n循环n次所得,因此,在log2n的代码上,加入一个n次循环即可。代码如上

O(n3)
n3是n2在外面加了一个n次所得。代码参考n2的。

除了上述常见的外,还有一些根据算法求得的。代码具体如下:

void func(int n)
{     int i=0,s=0;
      while (s<n)
     {     i++;
           s=s+i;
     }
}

解:对于while语句,假设执行x次时循环结束,即s>=n.
所以:s=x(x+1)/2 >= n,加一个值使其相等
所以:x(x+1)/2+k = n
求得x的值为根号n:
时间复杂度为:
在这里插入图片描述
五、算法空间复杂度分析和计算
一个算法的存储量包括输入数据所占的空间、程序本身所占的空间和临时变量所占的空间。这里在对算法进行存储空间分析时只考察临时变量所占的空间
空间复杂度比较常用的有:O(1)、O(n)、O(n²)。

注*临时占用的存储空间:函数体内分配的空间

空间复杂度:用于量度一个算法在运行过程中临时占用的存储空间大小。
一般也作为问题规模n的函数,采用数量级形式描述,记作:
S(n) = O(g(n))

算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)

int fun(int n)
{     int i, j, k, s; 
       s=0;
       for (i=0;i<=n;i++)           
            for (j=0;j<=i;j++)  	
                  for (k=0;k<=j;k++)     
                        s++; 
    return(s);
}

算法中临时分配的变量个数与问题规模n无关,所以空间复杂度均为O(1)。

若一个算法的空间复杂度为O(1),则称此算法为原地工作或就地工作算法。

int[] m = new int[n]
for(i=1; i<=n; ++i)
{
   j = i;
   j++;
}

这段代码中,第一行new了一个数组出来,这个数据占用的大小为n,其它行没有在分配新的空间,因此,这段代码的空间复杂度主要看第一行即可,即 S(n) = O(n)

注* : n2是n的2次方。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值