算法的概念/特征+算法效率衡量+时间复杂度和“大O记法”+测试list追加元素方法的效率+list/dict各种方法的时间复杂度总结+数据结构导学+抽象数据类型

QAQ数据结构第一天,开心思密达


目录

 

算法的概念

算法的五大特征

算法效率衡量

时间复杂度T与“大O记法”

在算法设计中我们关注的是:最坏时间复杂度和最优时间复杂度

时间复杂度的几条基本计算规则

常见的时间复杂度

测试list里面各种追加方法的效率

List里面的各种方法的时间复杂度总结

dict里面的各种方法的时间复杂度总结

数据结构导学

抽象数据类型


算法的概念

算法本质上是告诉计算机按照确切得步骤来执行一个指定的任务;

算法实际上就是解决问题的方法和思想,独立于编程语言。

算法的五大特征

(1)输入:算法的输入可以为0,也可以有多个输入(输入可有可无);

(2)输出:算法至少有1个或多个输出;

(3)有穷性:算法在有限的步骤之内解决问题,并且每一个步骤在可接受的时间内完成;

(4)确定性:算法中的每一步都有确定的含义,不会出现二义性,不能有歧义;

(5)可行性:思路是可以通过计算机语言实现的,每一步都是可行的。

算法效率衡量

对于同一问题,可能有多种解决算法,在算法实现中,我们对程序执行的时间进行测算,实现算法的执行时间可以反映处算法的效率,即算法的优劣。

注意:时间一定能够反映效率吗?有时候在性能比较低的计算机中,也不一定能通过时间表现出效率

#a+b+c = 1000, 且a的平方加b的平方=c的平方
#利用枚举法来做

'''
思路:
a从0 开始
b从0 开始
c从0 开始
一个一个试着来
使用到了嵌套结构
'''


'''
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分别为:{0},{1},{2}".format(a, b, c))

end_time = time.time()
print(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
105.38611555099487
finished
可以看出来,一共的用时时间为105.4秒钟
让计算机以最笨的方式来计算的

'''


import time

start_time = time.time()
for a in range(0, 1001):
    for b in range(0, 1001):
        c = 1000 - a - b
        if a**2 + b**2 == c**2:
            print("a,b,c分别为:{0},{1},{2}".format(a, b, c))

end_time = time.time()
print(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
0.9354948997497559
finished
可以看出来,效率提高了很多
'''

时间复杂度T与“大O记法”

时间复杂度是判断代码运行效率的标准。这里是时间复杂度可以看做计算规模,例如循环的次数。

对于算法的运行步骤进行分析,分析得越详细,越能够体现其复杂程度

但是,并不需要计算得特别精准,我们只需要进行大概的估算

我们基本可以把N^3(N的三次方)* 2 和N^3(N的三次方)*10和N^3(N的三次方)都是一个数量级,基本是一个等级上的。涉及到渐进函数的问题(反正也不重要,重要的是N,不是而不是常数系数)

“大O记法”实际上就是忽略常数系数,只关注N的数量级

在算法设计中我们关注的是:最坏时间复杂度和最优时间复杂度

1、最坏时间复杂度—算法完成工作最多需要多少基本操作;

最坏时间复杂度提供了一种保证,表明算法在这种程度的基本操作中一定可以完成工作

2、最优时间复杂度—算法完成工作最少需要多少基本操作;

3、平均时间复杂度—算法完成工作平均需要多少操作。

时间复杂度的几条基本计算规则

对于基本步骤来说,只有常数项,认为其时间复杂度为O(1),即为1

顺序、条件语句、循环这三个组合到一起基本上可以囊括所有的算法实现

顺序就是基本步骤之间的累加:
循坏结构要用乘法进行计算;

分支结构要考虑最长的步骤,考虑的是最坏时间复杂度

判断一个算法的效率时,往往只需要关注操作数量的最高此项,其他次要项和常数项可以忽略;

如果没有特殊说明,我们分析的算法时间是最坏时间复杂度

常见的时间复杂度

执行次数函数单例

非正式术语

12,只有顺序步骤

O(1)

常数阶

2n+3

O(n)

线性阶

3n^2+ 2n+1

O(n^2)

平方阶

5log(2)n+20

O(logn)

对数阶

3n+3nlog(2)n+19

O(nlogn)

nlogn

6n^3+2n^2+3n+4

O(n^3)

立方阶

2^n

O(2^n)

指数阶

 

记忆要点:
O(1)< O(logn) < O(n)< O(nlogn)< O(n^2)< O(n^3) < O(2^n) <O(n!) < O(n^n)

测试list里面各种追加方法的效率

timeit模块

timeit模块里面的Timer方法

Timer(“测试代码”, “让你的代码跑起来需要的条件”, timer(不用管))

Timer的timeit方法是可以反复操作多次返回的一个平均值

def t1():
    li4 = []
    for i in range(10000):
        li4.append(i)


def t2():
    li5 = []
    for i in range(10000):
        li5 += [i]  #这种形式的累计操作是优化的,执行效率远高于li5 = li5 + [i]

def t3():
    li6 = [i for i in range(10000)]


def t4():
    li7 = list(range(10000))

def t5():
    li8 = []
    for i in range(10000):
        li8.extend([i])

timer1 = Timer("t1()", "from __main__ import t1")
print("append:", timer1.timeit(1000))

timer2 = Timer("t2()", "from __main__ import t2")
print("+:", timer2.timeit(1000))

timer3 = Timer("t3()", "from __main__ import t3")
print("列表推导式:", timer3.timeit(1000))

timer4 = Timer("t4()", "from __main__ import t4")
print("range:", timer4.timeit(1000))

timer4 = Timer("t5()", "from __main__ import t5")
print("extend:", timer4.timeit(1000))

'''
append: 0.5824885000000001
+: 0.6853064999999999  #已经优化过了的效率较高
列表推导式: 0.28027329999999995
range: 0.1692867
extend: 0.8408731000000003

照理说+是最慢的方法,最不建议采纳的
'''

def t6():
    li = []
    for i in range(10000):
        li.append(i)  #从尾部添加元素


def t7():
    li = []
    for i in range(10000):
        li.insert(0, i) #从头开始添加元素

timer6 = Timer("t6()", "from __main__ import t6")
print("append:", timer6.timeit(1000))

timer7 = Timer("t7()", "from __main__ import t7")
print("insert:", timer7.timeit(1000))

'''
append: 0.5251785
insert: 25.314356
'''

List里面的各种方法的时间复杂度总结

 

索引、队尾添加都是O(1),pop(i)、insert(i,item)是O(n)

dict里面的各种方法的时间复杂度总结

 

算法重点关注的是问题的解决步骤,并没有关注数据的类型


数据结构导学

数据结构解决的问题是:一组数据如何保存,保存形式是怎样的

数据是一个抽象的概念,将其进行分类后就是python中的基本类型:int,float,char等;数据结构是将一组数据放在一起的形式,python有一些已经封装好的数据结构:列表、元组和字典,而有的数据结构需要我们自己去定义

程序= 数据结构+算法

#储存一组班级信息,不考虑重名的情况下,有以下几种方式:
[
    ("高宇星", "24", "山西"),
    ("韩敏", "18", "山西"),
    ("胖头鱼", "20", "河北"),
    ("饼饼", "21", "山西"),
]

for stu in student:
    if stu[0] == "高宇星"
    print(stu[0], stu[1], stu[2]


[
    {"name": "高宇星", "age": "24", "hometown":"山西"},
    {"name": "韩敏", "age": "18", "hometown": "山西"},
    {"name": "胖头鱼", "age": "20", "hometown": "河北"},
    {"name":"饼饼", "age": "21", "hometown": "山西"},
]



{
    "高宇星": {"age": 17, "hometown": "shanxi"}
}

print(stu["高宇星"])
print(stu.get["高宇星"])

#查找一个学生的信息,如果是列表的形式,需要遍历所有的信息,如果是字典的形式,我们直接可以锁定“键”去找值

抽象数据类型

将数据和操作的方式放在一起就是数据类型

先把数据的保存方式定好,然后把这个数据结构支持的方法定义好,如果执行还不需要考虑,先创建一个接口

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值