Python(算法和数据结构引入)

引入:
如果a+b+c = 1000 ,且 a2+ b2 = c2(a,b,c为自然数)。如何求出所有的a、b、c可能的组合

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

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**2 + b**2 == c**2 and a+b+c == 1000:
                print('a的值为:%d,b的值为:%d,c的值为:%d'%(a,b,c))



#计算程序结束的时间
end_time = time.time()

print('程序运行花费了%f时间'%(end_time-start_time))
#运行结果需要花费了大量的时间
a的值为:0,b的值为:500,c的值为:500
a的值为:200,b的值为:375,c的值为:425
a的值为:375,b的值为:200,c的值为:425
a的值为:500,b的值为:0,c的值为:500
程序运行花费了819.663406时间

算法的概念
算法是计算机处理信息的本质,因为计算机程序的本质上是一个算法来告诉计算机的步骤来执行一个指定的任务,一般地,当算法在处理信息时,会在输入设备或数据的存储地址读取数据,把结果写入输出设备或某个存储地址以后在调用。
算法是独立存在的一种解决问题的方法和思想
对于算法而言,实现的语法并不重要,重要的是思想
算法是可以有不同的语言描述实现版本如(c语言,c++描述,Python描述等),我们现在是在用Python语言进行描述实现

算法的五大特征

  • 输入:算法具有0个或多个输入
  • 输出:算法至少有1个或多个输出
  • 有穷性:算法在有限的步骤之后会自动结束而不会无线循环,并且每一个步骤可以在可接受的时间内完成
  • 确定性:算法中的每一步都有确定的含义,不会出现二义性
  • 可行性:算法的每一步都是可行的,也就是说每一步能够执行有限的次数完成

将代码进行优化
第二次尝试

import time

#计算程序开始的时间
start_time = time.time()
for a in range(0,1001):
    for b in range(0,1001):
        '''
        分析:如果a的值已经知道了,b的值也知道了,那么c的值,我们可以手动计算出c的值吧
        '''
        c = 1000 - a - b
        if a**2 + b**2 == c**2:
            print('a的值为:%d,b的值为:%d,c的值为:%d'%(a,b,c))

#计算程序结束的时间
end_start = time.time()

print('程序运行花费了%f时间'%(end_start-start_time))

优化后的程序大大减少了程序消耗的时间
运行结果:

a的值为:0,b的值为:500,c的值为:500
a的值为:200,b的值为:375,c的值为:425
a的值为:375,b的值为:200,c的值为:425
a的值为:500,b的值为:0,c的值为:500
程序运行花费了0.863724时间

算法效率衡量
执行时间反应算法效率
对应同一个问题,我们给出了两种解决算法,在两种算法的实现中,我们可以对程序的执行的时间进行了推算,发现两段代码程序执行的时间相差悬殊在(819.6634060.863724),由此我们可以得出结论:实现算法程序的执行时间可以反应出算法的效率,即算法的优劣

单靠时间绝对值可信吗 ?

  1. 测试结果非常依靠测试环境

    测试环境中的硬件的不同会对测试结果有很大的影响。比如:我们拿同一段代码,分别用Inter Core i9处理器和Inter Core i3处理器来运行,不用说,i9处理器要比i3处理器执行的速度要快,等我们换到另一台原来在这台机器上a的代码比b代码要快,等我们换到另一台机器上是,可能会有截然相反的结果。

  2. 测试结果受数据规模的影响很大

    对同一个排序算法,待排序数据的有序不一样,排序的执行时间就会有很大的差别。极端的情况下,如果数据已经是有序的,那排序算法不需要做任何的操作,执行结果可能无法真实地反应算法的性能,就可以粗略地估计算法的执行效率的方法

大O复杂度表示法
算法的执行效率,粗略来讲,就是算法代码执行的时间,但是,如何在不运行的情况下,用“肉眼”得到一段代码的执行时间?

for a in range(0,1001):
    for b in range(0,1001):
        for c in range(0,1001):
            if a**2+b**2 == c**2 and a+b+c == 1000:
                print('a的值为%d,b的值为%d,c的值为%d'%(a,b,c))

通过这段代码执行时间的推导过程,我们可以得到一个非常重要的规律,那就是,所有代码的执行时间T(n)与每行代码的执行次数n成正比

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

其中,T(n)它表示代码执行的时间;n表示数据规模的大小;f(n)表示代码执行的次数总和

T(n) = O(n^3*2)这就是大O时间复杂度表示法,大O时间复杂度实际上并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,所以也叫渐进时间复杂度(简称:时间复杂度)

  • 当n很大时,你可以把它想象成10000、100000而公式中的低阶、常量、系数,只需要记录一个最大阶的量级就可以了

时间复杂度分析


1、只关注循环执行次数最多的一段代码
大O这种复杂度表示的方法只是表示一种变化趋势。我们通常会忽略公式中的常量、低阶、系数,只需要记录一个最大阶的量级就可以了。所以,我们在分析一个算法、一段代码的时间复杂度的时候,也只关注循环执行次数最多的那一段代码就可以了。这段核心代码执行次数的n的量级,就是整段要分析代码的时间复杂度。

def cal(n):
    sum = 0
    i = 0
    for i in range(n+1):
        sum += i
        i += 1
    return sum

其中第2、3行代码都是常量级的执行时间,与n的大小无关,所以对于复杂度并没有影响。循环执行次数最多的是第4、5行代码,所以这块代码要终点分析。这两行代码执行了n次,所以总的时间复杂度就是O(n)

2、加法法则:总复杂度等于量级最大的那段代码的复杂度

def cal(n):
    sum = 0
    i = 1
    for i in range(100):    #该for循环的时间复杂度为O(1)
        sum += i
    for i in range(n+1):    #该for循环的时间复杂度为O(n)
        sum += i
    for i in range(n+1):    #当前有嵌套循环,时间复杂度为O(n^2)
        for j in range(n+1):
            pass

综合这段代码的时间复杂度,我们可以取出最大的量级。所以我们整段代码的时间复杂度为O(n^2)。也就是说,总的时间复杂度就等于量级最大的那段代码的时间复杂度

最坏时间复杂度
分析算法时,存在的几种可能的考虑:

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

对应列表排序,要查找的变量x可能出现数组的任意位置。如果数组中的第一个元素正好要查找的变量x,那就不需要继续遍历剩下的n-1个数据了,那时间复杂度就是O(1)。但如果数组中不存在变量x,那我们就需要把整个数组的遍历一遍,时间发复杂度就成了O(n)。。所以,不同情况下,这段代码的时间复杂度是不一样的

  • 对于最优时间复杂度,其价值表达,应为它没有提供什么有用信息,其反映的只是最乐观,最理想的情况,没有参考价值
  • 对于最坏时间复杂度,提供了一种保证,表明算法在此种程度的基本操作中一定能完成工作
  • 对于最平均时间复杂度,是对算法的一个全面评价,因此它完整全面的反映了这个算法的性质。但另一方面。这种衡量并没有保证,不是每个计算都能在这个基本操作内完成。而且,对于平均情况的计算,也会因为应用算法的实例分布可能并不均匀而难以计算,因此,我们主要关注算法的最坏情况,亦即最坏时间复杂度
    常见的时间复杂度
    常见的复杂度并不多,从低阶到高阶有:O(1)、O(logn)、O(nlogn)、O(n2)
执行次数举例 非正式术语
12 O(1) 常数阶
2n+3 O(n) 线性阶
3n2+3n+1 O(n2) 平方阶
log2n+20 O(logn) 对数阶
2n+3nlog2n+19 O(nlogn) nlogn阶
2n O(2n) 指数阶

timeit模块
timeit模块可以用来测试一小段Python代码的执行速度

class timeit.Timer(stmt='pass',setup='pass',timer=<timer functiom>) 
Timer是测量小段代码执行速度的类
stmt参数是测试的代码语句(statment)
setup参数是运行代码时需要的设置;
timer参数是一个定时器的函数,与平台有关

timeit.Timer.timeit(number=1000000)
Timer类中测试语句执行速度的对象方法。number参数是测试代码时的测试次数,默认为1000000次。方法返回代码的平均耗时,一个float类型的秒数

from  timeit import Timer

def ts1():
    l = []
    for i in range(1000):
        l = l+[i]   #不能列表加数字,但能列表加列表

def ts2():
    l = []
    for i in range(1000):
        l.append(i)   #追加,从末尾添加

#列表推导式
def ts3():
    l = [i for i in range(1000)]

def ts4():
    l = list(range(0,10))

def ts5():
    l = []
    for i in range(1000):
        l.insert(0,i)    #从头开始添加

#当前文件的名字
t1 = Timer("ts1()","from __main__ import ts1")
print('t1时间为:',t1.timeit(number=1000))
t2 = Timer("ts2()","from __main__ import ts2")
print('t2时间为:',t1.timeit(number=1000))
t3 = Timer("ts3()","from __main__ import ts3")
print('t3时间为:',t1.timeit(number=1000))
t4 = Timer("ts4()","from __main__ import ts4")
print('t4时间为:',t1.timeit(number=1000))
t5 = Timer("ts5()","from __main__ import ts5")
print('t5时间为:',t1.timeit(number=1000))

运行结果:

#答案不唯一
t1时间为: 1.012796
t2时间为: 0.06185889999999983
t3时间为: 0.024930399999999908
t4时间为: 0.00043779999999982167
t5时间为: 0.2534044999999998

经过测试我们发现t4的时间会比较快

数据结构
我们如何用Python的类型保存一个班的学生信息?如果想要快速的通过学生姓名获取其信息呢?

实际上我们思考这个问题的时候,就已经用到数据结构。列表和字典都可以存储一个班的学生信息,但是想要在列表中获取一名同学的信息时,就要遍历这个列表,其时间复杂度为O(n),而使用字典存储时,可将学生姓名作为字典的键,学生信息作为值,进而查询时不需要遍历便可以快速获取学生的信息,其时间复杂度为O(1)

我们为了解决这个问题,需要将数据保存下来,然后根据数据的存储方式来设计算法实现进行处理,那么数据的存储方式不同就会导致需要不同算法进行处理。我们希望算法解决问题的效率越快越好,于是我们就需要考虑数据究竟如何保存的问题,这就是数据结构。

在上卖弄的问题中我们可以选择Python中的列表或字典中的存储学生信息。列表和字典就是Python内建帮我们封装好的两种数据

概念
数据是一个抽象的概念,将其进行分类后得到程序设计中的基本类型。如:int,float,char等。数据元素之间不是独立的,存在特定关系,这些关系便是结构。数据结构指数据元素之间的关系。

Python给我们提供了很多现成的数据类型,这些系统自己定义好的,不需要我们自己去定义的数据结构叫做Python的内置数据结构。比如列表、元素、字典而有些数据组织方式,Python系统里面没有直接定义,需要我们自己去定义实现这些数据的组织方式,这些数据组织方式称之为Python的扩展数据结构,比如栈,队列等。

算法与数据结构的区别
数据结构只是静态的描述了数据元素之间的关系
高效的程序需要在数据的基础上设计和选择算法
程序 = 数据结构 + 算法
总结:算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体

在这里插入图片描述

发布了54 篇原创文章 · 获赞 26 · 访问量 6182

猜你喜欢

转载自blog.csdn.net/qq_37662827/article/details/103568919