概念
数据结构和算法是程序员的兵法,用于提高代码运行效率和性能
算法
算法是计算机处理信息的本质,程序本质上是一个算法来告诉计算机确切的步骤来执行一个指定的任务,是为了解决实际问题而设计
数据结构
数据结构指数据对象中数据元素之间的关系。数据结构是算法需要处理的问题载体。
算法效率衡量
例子
如果 a+b+c=1000,且a2 + b2 = c2(a,b,c为自然数),如何求a,b,c
思路1:枚举法遍历
a =0 …1000
b =0 …1000
c =0 …1000
import time
start_time=time.time()
for a in range(1000):
for b in range(1000):
for c in range(1000):
if a+b+c==1000 and a**2 + b**2 == c**2:
print("a,b,c:%d, %d, %d"% (a,b,c))
end_time=time.time()
print("times:%f" % (end_time-start_time))
print("finished")
输出结果
a,b,c:0, 500, 500
a,b,c:200, 375, 425
a,b,c:375, 200, 425
a,b,c:500, 0, 500
times:183.689066
finished
实现算法程序的执行时间可以反应出算法的效率,即算法的优劣。
思路2:枚举法遍历
a =0 …1000
b =0 …1000
c =1000-a–b
import time
start_time=time.time()
for a in range(1000):
for b in range(1000):
c = 1000-a-b
if a**2 + b**2 == c**2:
print("a,b,c:%d, %d, %d"% (a,b,c))
end_time=time.time()
print("times:%d" % (end_time-start_time))
print("finished")
输出结果
a,b,c:0, 500, 500
a,b,c:200, 375, 425
a,b,c:375, 200, 425
a,b,c:500, 0, 500
times:1.819427
finished
实现算法程序的执行时间可以反应出算法的效率,即算法的优劣。但是不同的机器环境,不同性能,会导致时间不能 作为衡量标准。
时间复杂度和大O表示法
算法对于不同的机器环境而言,确切的单位时间是不同的,但是对于算法进行多少个基本操作(即花费多少时间单位)在规模数量级上却是相同的,由此可以忽略机器环境的影响而客观的反应算法的时间效率。
-
时间复杂度:假设存在函数g,使得算法A处理规模为n的问题示例所用时间为T(n)=O(g(n)),则称O(g(n))为算法A的渐近时间复杂度,简称时间复杂度,记为T(n)
-
大O表示法:一个单调的整数函数f,存在充分大的n总有f(n)<=c*g(n),就说函数g是f的一个渐近函数(忽略常数),记为f(n)=O(g(n))。也就是说,在趋向无穷的极限意义下,函数f的增长速度受到函数g的约束,亦即函数f与函数g的特征相似
时间测量模块
timeit模块:
timeit.Timer('操作代码','类似导入设置', timer=<timer function>)
# 运行代码10000次返回平均耗时
timeit.Timer.timeit(number=10000)
python列表类型的时间效率
from timeit import Timer
def test1():
l = []
for i in range(1000):
l = l + [i]
def test2():
l = []
for i in range(1000):
l += [i]
def test3():
l = []
for i in range(1000):
l.append(i)
def test4():
l = []
for i in range(1000):
l.extend([i])
def test5():
l = [i for i in range(1000)]
def test6():
l = list(range(1000))
if __name__ == '__main__':
t1 = Timer('test1()', 'from __main__ import test1')
print("concat:", t1.timeit(number=1000), "seconds")
t2 = Timer('test2()', 'from __main__ import test2')
print("+=:", t2.timeit(number=1000), "seconds")
t3 = Timer('test3()', 'from __main__ import test3')
print("append:", t3.timeit(number=1000), "seconds")
t4 = Timer('test4()', 'from __main__ import test4')
print("extend:", t4.timeit(number=1000), "seconds")
t5 = Timer('test5()', 'from __main__ import test5')
print("iter:", t5.timeit(number=1000), "seconds")
t6 = Timer('test6()', 'from __main__ import test6')
print("list():", t6.timeit(number=1000), "seconds")
输出结果
concat: 1.988459133 seconds
+=: 0.15857361200000009 seconds
append: 0.14816275800000023 seconds
extend: 0.23186704300000027 seconds
iter: 0.06949559800000005 seconds
list(): 0.03229362300000016 seconds
python列表和字典的时间复杂度
-
list内置操作的时间复杂度
-
dict内置操作的时间复杂度
常见时间复杂度
执行次数函数举例 | 阶 | 非正式术语 |
---|---|---|
12 | O(1) | 常数阶 |
2n+3 | O(n) | 线性阶 |
3n2+2n+1 | O(n2) | 平方阶 |
5log2n+20 | O(logn) | 对数阶 |
2n+3nlog2n+19 | O(nlogn) | nlogn阶 |
6n3+2n2+3n+4 | O(n3) | 立方阶 |
2n | O(2n) | 指数阶 |
- 所消耗的时间从小到大