数据结构与算法
1.好的算法可节省运算时间
1. 2.算法效率衡量
** 1.2.1时间复杂度**
算法完成工作最少需要多少基本操作,即最优时间复杂度(理想上限,实际意义不大)
算法完成工作最多需要多少基本操作,即最坏时间复杂度****(基础下限,可以评估算法的基础操作–主要关注这一项)**
算法完成工作平均需要多少基本操作,即平均时间复杂度**(对算法的全面评价)
1.2.2大O记法*–实际意义有限
其实类似于函数求了边界,看函数是否有上限,在n无穷大处单侧收敛
原理:“大O记法”:对于单调的整数函数f,如果存在一个整数函数g和实常数c>0,使得对于充分大的n总有f(n)<=c*g(n),就说函数g是f的一个渐近函数(忽略常数),记为f(n)=O(g(n))。也就是说,在趋向无穷的极限意义下,函数f的增长速度受到函数g的约束,亦即函数f与函数g的特征相似。
分析算法效率的主要部分。而计量算法基本操作数量的规模函数中那些常量因子可以忽略不计。例如,可以认为3n2和100n2属于同一个量级,如果两个算法处理同样规模实例的代价分别为这两个函数,就认为它们的效率“差不多”,都为n2级。
时间复杂度的几条基本计算规则
基本操作,即只有常数项,认为其时间复杂度为O(1)
顺序结构,时间复杂度按加法进行计算
循环结构,时间复杂度按乘法进行计算
分支结构,时间复杂度取最大值(就是哪个分支的计算次数多就按哪个算)
判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略
在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度
时间复杂度计算本质上就是根据各条语句计算执行所需时间(或者说是执行一次运算的时间相同,我们需要计算语句各执行了多少次)
1.5算法分析实践:
三个循环:n3
一个分支语句和print可看成两个正常的顺序语句,=2
所以该算法的函数可写为:
f(n)=n3+2
只看最高次项,时间复杂度可写作:
T(n) = O(nnn) = O(n3)
f(n)=n*2+1+1+1
时间复杂度:
T(n) = O(nn(1+1)) = O(n*n) = O(n2)
常见的时间复杂度:
1.
所消耗的时间从小到大
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
Python内置类型性能分析
1.timeit模块—测试一段python代码的执行速度
class timeit.Timer(stmt=‘pass’, setup=‘pass’, timer=)
Timer是测量小段代码执行速度的类。
stmt参数是要测试的代码语句(statment);
setup参数是运行代码时需要的设置;
timer参数是一个定时器函数,与平台有关
timeit.Timer.timeit(number=1000000)----number是测试代码时 的测试次数
方法返回执行代码的平均耗时,一个float类型的秒数。
时间计算模块应用:
注意启动文件默认是main
1.list
2.pop
数据结构:
1.列表元组字典等式py内已经定义好的数据结构
2.Python里没直接定义,需要自己定义实现这些数据的组织方式,这些数据组织方式称之为Python的扩展数据结构,比如栈,队列等
算法与数据结构的区别
1.数据结构只是静态的描述了数据元素之间的关系。
高效的程序需要在数据结构的基础上设计和选择算法。
程序 = 数据结构 + 算法
总结:算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体
抽象数据类型(Abstract Data Type)
抽象数据类型(ADT)的含义是指一个数学模型以及定义在此数学模型上的一组操作。
即把数据类型和数据类型上的运算捆在一起,进行封装。
如何定义:
ADT ComplexNumber:#定义复数抽象数据类型
ComplexNumber(float a,float b)# 构造复数a+bi
+(ComplexNumber c1,ComplexNumber c2)# 求复数c1 + c2
-(ComplexNumber c1,ComplexNumber c2)# 求复数c1 - c2
*(ComplexNumber c1,ComplexNumber c2)#求复数c1 * c2
/(ComplexNumber c1,ComplexNumber c2)#求复数c1 / c2
getReal(ComplexNumber c1)# 获取c1的实部
getImaginary(ComplexNumber c1)# 获取c1的虚部
如上,定义了数据类型的名称以及可操作的方法,但是各个方法具体内容则不展示(自己另写),相当于只写了接口
使用者只关心提供了那些接口,并不关心这些接口是如何实现的(向用户隐藏了)。
实现者关心这些接口怎样具体的实现。
生活中的例子:ADT相当于插座向用户提供了接口。
引入抽象数据类型的目的是把数据类型的表示和数据类型上运算的实现与这些数据类型和运算在程序中的引用隔开,使它们相互独立。
最常用的数据运算有五种:
插入
删除
修改
查找
排序
例: