数据结构与算法系列(一):时间复杂度和空间复杂度

版权声明:转载请注明出处^_^ https://blog.csdn.net/zhou307/article/details/84452454

前言

本篇开始,梳理总结数据结构与算法。虽然开的系列都比较多,可是都很重要。
数据结构和算法是区分程序员和码农的标志之一,当然我认为软件工程师比程序员更高级一些哈。
系列中每篇都是消化吸收以后再整理的,以此来标识自己这部分已经理解了。
咳咳咳,我们学习他们的目的也只是为了应用,像是什么数据推理证明之类的,呃,脱离场景都是耍流氓,我又不做算法方向,花这么大经历去研究证明过程之类的,mdzz吗?所以以后文章都是偏应用方向。

推荐书单

不负责推荐一波,当然都是广受好评的。只看过《算法》。可能配合着看更好吧
入门:《大话数据结构》,《算法图解》
系统学习:《数据结构与算法描述》
大部头:《算法(第4版)》

基础

如果说数据结构和算法是编程的基础之一的话,那么接下来几个概念就是数据结构与算法的通用基础:

  • 时间复杂度
  • 空间复杂度

而他俩的理论基础又是:

  • 大O表示法
  • 几个小小数学方面的

OK,一个个来。

基础的基础

大O表示法

先来看两个函数的坐标图像,他们是:
f ( n ) = l o g n , f ( n ) = n 2 f(n) = logn,f(n) = n ^ 2
坐标图为:
在这里插入图片描述
可以看到,黄色曲线的增长趋势远远大于蓝色曲线的增长趋势。此时,n才取值30,如果 n n → \infty
那么二者的差异将会非常非常大。
在算法领域中,这个增长趋势我们就用 大O表示法 表示。
所以 O ( n 2 ) O(n^2)
就表示 纵坐标y的值横坐标n 的增长趋势,该增长趋势就是 n 2 n^2 这个函数的图像。
说完了,关于 y轴 具体指代什么,稍后再说。

几个数学方面的

上文说的大O表示法,我们可以在 n 1 n→\infty (式1) 的情境下去看。
比如 n 2 + n + 1 2 n^2 + n + 1 (式2) ,当处于 式1 的情况下,由于 大O表示法 表达的是 y轴数值的增长趋势。假如 n 分别等于 1,1亿,很明显,起决定作用的是:
n = 1 : n 2 = 1 , n = 1 ; 当n = 1 时:n^2 = 1, n = 1;
n = 1 亿 : n 2 = 1 亿 亿 n = 1 亿 当n = 1亿时:n^2 = 1亿亿,n = 1亿。
很明显,是 n 2 n^2
所以 O ( n 2 + n + 1 ) O ( n 2 ) O(n^2 + n + 1) ≈ O(n^2)
。说这个的意思呢,就是说尽管 式2 是一个多项式,但是在大O分析法的场景下,我们只看对于增长趋势影响最大的项。
证明也很好证明:增长趋势顾名思义就是增长比例么,也就相当于是 y / x
式子2除以 n以后就变成了:
n + 1 + 1 n , n n + 1 + \frac{1}{n}, n → \infty ,可以进一步简化成 n n
所以对于增长趋势影响最大的就是第一项, n 2 n^2

常见的函数图像

在算法领域中,总共就几种需要掌握的函数图像,如下图:
在这里插入图片描述
在大O表示法下,他们表示的都是增长趋势,大家可以除以n后自行证明哪个大哈,看图也一样。
结论:
2 n > n 2 > n l o g ( n ) > n > l o g ( n ) > 1 ( ) 2 ^ n > n ^2 > nlog(n) > n > log(n) > 1(常数)

时间与空间复杂度

评价算法性能就是看 运行时间 和 存储空间 占用的。为什么是这两个参数呢?
我认为应该是这样子的:结合冯诺依曼体系结构来看,计算机由:存储器,计算器,控制器和输入输出设备组成。而输入输出设备和控制器无需考虑,所以就剩下存储器和计算器了。算法在单台机器上来说不就是要减少计算和存储吗?愚见。
嗯,所以就引出了 时间复杂度空间复杂度 的概念。

时间复杂度

上文的大O表示法中,y轴的坐标值一直没有具体定义。我们假设机器执行每条指令的时间都是一样,比如是1个时间单位,所以就相当于执行c条指令花费的时间单位就是c。
在分析算法的时间复杂度时,我们把大O表示法的纵坐标轴表示为 程序执行花费的时间(或者说指令执行的次数),所以:
时间复杂度O(n)就表示为:程序正确执行完毕花费时间的增长趋势。而具体 O ( n 2 ) O ( n l o g n ) O(n^2) 是否大于O(nlogn) 则是看括号中的函数,也就是上文中的图片,可知,是大于的。

空间复杂度

和时间复杂度一样,在计算空间复杂度时,O(n)就表示 程序正确执行完笔花费空间的增长趋势,实际要比时间复杂度情景下简单。

简单练习

做个练习表示结束,分成两讲吧,快写吐了。
比如,分析下列程序的时间和空间复杂度:

void atom(int n) {
	int arr[n];
	int i;
	
	for (int i = 0; i < n; i++) {
		arr[i] = i;
	}
} 

时间复杂度为:不论n多大,2,3行代码都是1次,第5行for循环体内是n次,第6行for循环体内为n次,所以总体为:n + n + 1 + 1,我们学习过,只看影响最大的,那么就是 2n,进一步简化成几个基本函数,最终就是 n。所以:
时间复杂度为:O(n)。
空间复杂度为:i 之占1个单位,arr 数组占n个,所以最终:
空间复杂度为:O(n)

猜你喜欢

转载自blog.csdn.net/zhou307/article/details/84452454