python进阶 - 01 算法与数据结构导入

一、算法的导入

1.1 算法的概念

算法是解决问题的一种思想或方法

如果 a+b+c=1000,且 a ** 2+b ** 2=c ** 2(a,b,c 为自然数),如何求出所有a、b、c可能的组合?

第一种方式

		import time
		start_time = time.time()
		for a in range(0,1001):
		    for b in range(0,1001):
		        for c  in range(0,1001):
		            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()
		tot_time = end_time - start_time
		print(tot_time)

解决以上问题的方法就是一个算法(枚举法)。

1.2 算法的五大特性

1.输入:算法至少有0个或1个输入
2.输出:算法至少有1个或多个输出
3.有穷性:算法会在一定的步骤内结束而不会无限循环
4.确定性:算法中每一步都有确定的含义,不存在二义性
5.可行性:算法中的每一步都可以执行,也就是说算法的每一步都可以在有限的循环内完成

二、衡量算法的效率

第二种方式:

	    import time
		start_time = time.time()
		for a in range(0,1001):
		    for b in range(0,1001-a):
		        c = 1000 - a - b
		        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()
		tot_time = end_time - start_time
		print(tot_time)

第一种方式所用的时间远大于第二种方式,我们可以仅仅依靠算法执行的时间来衡量算法的优劣吗?

这种方式是不准确的,因为算法执行的时间还受到测试环境(电脑性能高低)和数据规模的影响。但在算法执行过程中,算法执行的基本运算步数是固定的,因此我们可以根据算法执行 步骤的多少来粗略衡量算法的优劣

2.1 大O时间复杂度表示法

                 T(n) = O(f(n))

T(n) 算法执行的总时间
n      数据规模
f(n)  基本运算的次数
O     表示T(n)与f(n)成正比,即随着f(n)的增加,T(n)也在不断增加

用大O表示法来分析第一种算法:

      第一种算法的总执行步数: 1000*1000*1000*2 
      可抽象为     n^3 *2
      T(n)  = O(n^3 *2)

当n很大的时候,公式中的常量、地阶或系数三部分并不左右增长趋势,因此只需要考虑最大量级即可。

第二种方式的大O时间复杂度为O(n^2)

2.2 时间复杂度分析的方式

1.只关注循环次数最多的一段代码

			def cal(n):
			
			  #无论n等于几,以下两行代码只执行一次,是常数阶,因此这两行代码对时间复杂度没有影响
			    sum = 0     
			    i = 1

              当n = 4时,for循环执行了4次,因此这段代码的时间复杂度为O(n)
			    for i in range(n):
			        sum += i
			        i += 1
			    return sum
			
			print(cal(4))

以上代码的时间复杂度为O(n),即循环次数最多的一段代码的复杂度

2.加法规则:总复杂度等于量级最高的那段代码的复杂度

    def cal(n):
		sum = 0
		i = 1

       #无论n等于几,以下for循环都会循环100次,其时间复杂度为O(1),是常数阶
		for i in range(100):
			sum += i
		
		 #当n =4时,以下for循环会循环5次,f(n) = n +1 ,不考虑常数项,其时间复杂度为O(n)
		for i in range(n+1):
			sum += i
			i+=1
		
		#当 n = 4时,以下for循环会循环5次,ff(n) = n^2 +2n +1,不考虑低阶和常数项,其时间复杂度为O(n^2)	
		for i in range(n+1):
			for j in range(n+1):
				pass
  
     print(cal(4))

该段代码的总时间复杂度为O(1) + O(n) + O(n^2),只考虑最大量级的一段代码的复杂度,则该代买的时间复杂度为T(n) = O(n ^ 2)

2.3 最坏时间复杂度

算法完成工作最少需要多少基本操作,即最优时间复杂度
算法完成工作最多需要多少基本操作,即最坏时间复杂度
算法完成工作平均需要多少基本操作,即平均时间复杂度

例如:查找列表中的某一个元素,最优的时间复杂度是O(1),即列表元素位于列表的第一位

查找列表中的某一个元素,最坏的时间复杂度是O(n),即列表元素位于列表的最后一位

我们在考虑一个算法的时间复杂度时,一般只考虑最坏时间复杂度。

2.4 常见的时间复杂度

常数阶O(1)
对数阶O(logn)
线性阶O(n)
nlogn阶O(nlogn)
平方阶O(n^2)
指数阶O(a ^n)

三、Python内置类型性能分析

我们可以用Python自带的timeit模块中的Timer类来测量一个代码的执行时间
class timeit.Timer(stmt=‘pass’, setup=‘pass’, timer=)
stmt 要测试的代码语句
setup 是运行代码时需要的设置
timer 一个定时器函数,与平台有关

用不同的方式创建一个非空列表,各个方式的性能测试

       from timeit import Timer

		def test1():
		    l = []
		    for i in range(1000):
		        l = l + [i]
		
		def test2():
		    l = []
		    for i in range(1000):
		        l.append(i)
		
		def test3():
		    l = []
		    for i in range(1000):
		        l.extend([i])
		
		def test4():
		    l = [i for i in range(1000)]
		
		def test5():
		    l = []
		    for i in range(1000):
		        l.insert(0,i)
		def test6():
		    l = list(range(1000))
		
		def test7():
		    l = []
		    for i in range(1000):
		        l += [i]
		        
		t1 = Timer('test1()','from __main__ import test1')
		print('add执行时间:',t1.timeit(number=1000))
		
		t2 = Timer('test2()','from __main__ import test2')
		print('append执行时间:',t2.timeit(number=1000))
		
		t3 = Timer('test3()','from __main__ import test3')
		print('extend执行时间:',t3.timeit(number=1000))
		
		t4 = Timer('test4()','from __main__ import test4')
		print('推导式执行时间:',t4.timeit(number=1000))
		
		t5 = Timer('test5()','from __main__ import test5')
		print('insert执行时间:',t5.timeit(number=1000))
		
		t6 = Timer('test6()','from __main__ import test6')
		print('list执行时间:',t6.timeit(number=1000))
		
		t7 = Timer('test7()','from __main__ import test7')
		print('+=执行时间:',t7.timeit(number=1000))
		
        输出结果:
        add执行时间: 2.9384223547167485
		append执行时间: 0.2181493807683248
		extend执行时间: 0.3046907205620495
		推导式执行时间: 0.10262465739990567
		insert执行时间: 1.1072418832214757
		list执行时间: 0.03898072088704563
		+=执行时间: 0.25340575995785297

用不同方式删除一个字典中值的性能

from timeit import Timer

def te1():
    dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7}
    del(dict1['c'])

def te2():
    dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7}
    dict1.popitem()

def te3():
    dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7}
    dict1.pop('c')

t2 = Timer('te2()','from __main__ import te2')
print('popitem执行时间:',t2.timeit(number=1000))

t3 = Timer('te3()','from __main__ import te3')
print('pop执行时间:',t3.timeit(number=1000))

   输出结果为:
   popitem执行时间: 0.0009920934711697066
   pop执行时间: 0.0011038465288416947
   del执行时间: 0.0009225328944555099

四、数据结构导入

我们如何用Python中的类型来保存一个班的学生信息?

stu = [('小明','男','17'),('小李','女','17'),('小张','男','18')]

stu2 = {"小明":{"gender":"男","age":17},"小李":{"gender":"男","age":17},"小张":{"gender":"男","age":18}}

stu3 = [{"name":"小明","gender":"男","age":17},{"name":"小李","gender":"男","age":17},{"name":"小张","gender":"男","age":18}]

数据保存的方式或数据组合的方式其实就是数据结构。

算法是为了解决实际的问题,而数据结构是为了解决数据的问题。

程序 = 算法 +数据结构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值