目录
一.什么是数据结构?
二.什么是算法?
三.算法效率
1.如何衡量算法的好坏
2.算法的复杂度
四.时间复杂度
1.时间复杂度的概念
2.例题展示
五.空间复杂度
1.概念
2.注意事项
空间的销毁===>归还对空间的使用权内存空间属于操作系统的进程
3.类比理解
4.例题分析
六.小结
好久不见,uu们。沉淀了一个寒假,想必大家的水平一定突飞猛进了吧~
今天为大家呈现上的是数据结构的知识,一些关于时间复杂度和空间复杂度的理解。
规矩不乱,先赞后看~
一.什么是数据结构?
数据结构是计算机存储,组织数据的方式,之相互之间存在一种或多种特定关系的数据元素的集合,即在内存中管理数据(包括增删查改)
二.什么是算法?
算法是定义良好的计算过程,它取一个或一组值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列计算步骤,用来将输入数据转化为输出结果。
三.算法效率
1.如何衡量算法的好坏
怎么衡量算法的好坏呢?
比如对于斐波那契数列:
其递归实现方式非常简洁,但简洁就一定好吗?那如何来衡量好与坏呢?
2.算法的复杂度
算法在编写成可执行程序后,运行时需要耗费时间资源和空间(内存)资源。依次衡量一个算法的好坏,一般是从时间和空间两个维度来衡量,即时间和空间复杂度
时间复杂度主要是衡量算法运算的快慢,空间复杂度则是衡量一个算法运行所需的额外空间。在计算机发展的早期,计算机容量小,所有对空间复杂度很在乎,但经过计算机行业的发展,存储容量达到很高,故不再关心算法的空间复杂度
四.时间复杂度
1.时间复杂度的概念
时间复杂度的定义:再计算机科学中,算法的时间复杂度是一个函数(数学函数,不是c语言中的函数),它定量描述了该算法的运行时间,一个算法所耗费的时间,从理论上讲,是算不出来的,只有你把你的程序放在机器上跑起来,才知道。一个算法所花费的时间与其执行次数成正比
!!!算法的基本操作的执行次数,为算法的时间复杂度!!!
即:找到某条基本语句与问题规模N之间的数学表达式,就是算出该算法的时间复杂度!!!
但是
实际计算时间复杂度时,不一定精确执行次数,大概的就行---->** 大o的渐进表示法 **
O(N*N)===》表示估算
大O符号:适用于描述函数渐进行为的数学符号
推导大O阶的方法:
1.用常数1取代运行时间中所有的加法常数(O(1)不是代表一次,而是代表常数次(常数再大也是O(1)cpu运转很快,都是平等的被看作常数次))
2.在修改后的运行次数函数中,只保留最高阶项
3.如果最高阶项存在且不为1,即无限大的时候,则去除与这个项目相乘的常数,得到结果就为大O阶
另外还有些算法的时间复杂度存在最好,最坏,平均的情况
最坏:任意输入规模的最大运行次数(上界)
平均:任意输入规模的期望运行次数
最好:任意输入规模的最小运行次数(下界)
eg.再一个长度为N的数组中搜索一个数据x
最好情况:1次找到
最坏情况:N次找到
平均情况:N/2次找到
在实际中一般情况关注的是算法的最坏情况,所有数组中搜索数据时间复杂度为O(N)
2.例题展示
(1)
要计算这个程序的时间复杂度
F(N) = N * N + 2 * N + 10(实际计算没必要那么精确,只需要大概的执行次数----》大o的渐进表示法)
使用大O阶的渐进表示法后,func1的时间复杂度为:O(N*N)
(2)
计算该程序的时间复杂度
O(M+N) (两者大小关系不确定,因此需要两个同时才能确定时间复杂度)
(3)
时间复杂度为O(1)
O(1)不是代表一次,而是代表常数次
(4)
时间复杂度为O(N)
因为当N无限大的时候,倍数也可以忽略不计
(5)
时间复杂度为O(N)===>做最坏的打算,降低预期,底线思维!!!
(6)
冒泡排序的时间复杂度:O(N) = N * (N - 1)/ 2 = O(N*N)
N-1 N-2 N-3 N-4.。。。 3 2 1(等差数列)
(7)
二分查找的时间复杂度:O(logN)因为找一次就要分走一半,找x次就除x个2^x = N ---> x = logN
(8)
时间复杂度为O(N)递归N次(涉及函数栈帧的知识)
五.空间复杂度
1.概念
空间复杂度也是一个数学表达式,是对一个算法在运行过程中**临时**占用额外存储空间大小的量度。
空间复杂度不是程序占用了多少bytes的空间,因为这没有太大意义,所以空间复杂度算的是
变量的个数。
空间复杂度计算规则基本上和时间复杂度类似,也是用大O渐进表示法
!!!注意!!!:函数运行时所需要的栈空间(存储参数,局部变量,一些寄存器信息等)
在编译期间已经确定好了,因此空间复杂度主要是通过函数在运行时显示申请的额外空间来确定。
2.注意事项
空间的销毁===>归还对空间的使用权
内存空间属于操作系统的进程
3.类比理解
分配内存===>去酒店开房间(这时别人不能住)
销毁内存===>退房(退房后别人还能住)
进程==>酒店
空间==>酒店的房间
越界和野指针的本质:访问了不属于自己的内存(住别人的房间)
4.例题分析
(1)
计算BubbleSort的空间复杂度:O(1)<因为没有额外开辟临时的空间>
(2)
计算斐波那契数列的空间复杂度:O(N)<存在malloc开辟n的空间>
(3)
计算阶乘递归fac的空间复杂度:O(N) 递归存在函数栈帧从fac(N)到fac(1)N个空间
(4)
fib的空间复杂度:O(N) ==> 尽管是有两个函数相加,但却会从一个函数的栈帧进去,一直
往下走,直到到底之后才逐个释放,释放完之后另一个函数再重复使用上一次递归函数的空间,
故为O(N)
总结为:!!!递归看深度!!!
(5)
涉及函数栈帧的知识:
func1和func2的结果一定是相同的,因为在func1开辟和结束之后会归还原空间的使用权,
进行到func2时会将使用权给func2,故使用同一块地址
另外一个程序中存在两个a但不会报错:在不同的函数栈帧里面,因此不会出错
六.小结
看懂了这篇博文,uu们就大概掌握了时空建复杂度六成的功力,还剩四成就得自行摸索了。
总之,每天进步,时刻学习!
撤退~