python 数据结构

数据结构(python)

Day1

时间复杂度:实现同一个功能模块可以通过不同的算法,就好比去一个地方可以通过不同的路线不同的交通工具一样。时间复杂度就是量化这些算法达成最终目的所要用的步骤时间。

对程序运行的时间进行计算可以使用

import time
start = time.time()

#要执行的代码

end = time.time()

time = end - start      #对不同算法有个大致时间上的概念

大O记法:对不同时间复杂度进行量级上的划分。 就像是我们用的硬盘有些是TB级别,有些是GB级别,虽说TB级别下的硬盘容量也都不尽相同,但也可将他们划为一类。

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

基本操作,即只有常数项,认为其时间复杂度为O(1)
顺序结构,时间复杂度按加法进行计算
循环结构,时间复杂度按乘法进行计算
分支结构,时间复杂度取最大值
判断一个算法的效率时,往往只需要关注操作数量的最高次项,其它次要项和常数项可以忽略
在没有特殊说明时,我们所分析的算法的时间复杂度都是指最坏时间复杂度

常见时间复杂度

在这里插入图片描述
时间消耗: O ( 1 ) < O ( l o g n ) < O ( n ) < O ( n l o g n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n) O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

1⃣️个栗子:

#第一种
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, b, c: %d, %d, %d" % (a, b, c))

时间复杂度: T ( n ) = O ( n ∗ n ∗ n ) = O ( n 3 ) T(n) = O(n*n*n) = O(n^3) T(n)=O(nnn)=O(n3)

#第二种
for a in range(0, 1001):
    for b in range(0, 1001-a):
        c = 1000 - a - b
        if a**2 + b**2 == c**2:
            print("a, b, c: %d, %d, %d" % (a, b, c))

时间复杂度: T ( n ) = O ( n ∗ n ∗ ( 1 + 1 ) ) = O ( n ∗ n ) = O ( n 2 ) T(n) = O(n*n*(1+1)) = O(n*n) = O(n^2) T(n)=O(nn(1+1))=O(nn)=O(n2)

由此可见,我们尝试的第二种算法要比第一种算法的时间复杂度好多的。

关于列表

from timeit import Timer

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

def t2():
    li = []
    for i in range(10000):
        li = li + [i]
        # li += [i]

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

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

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

def t6():
    li = []
    for i in range(10000):
        li.append(i)

def t7():
    li = []
    for i in range(10000):
        li.insert(0, 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("[i for i in range]:", timer3.timeit(1000))

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

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

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

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

结果:

append: 0.6904560429999833
+: 133.750434496
[i for i in range]: 0.373120168000014
list(range()): 0.1752699119999761
extend: 0.9450534559999824
append 0.6623780410000109
insert(0) 18.39896798999996

可见:
在这里插入图片描述

在这里插入图片描述

Day2

顺序表

内存:不同类型的变量都存在内存里,并且占用的空间各不相同,比如int 占用的内存空间为四个字节(也就是32位,ps:每个平台不一样,现在普遍是这样,以前16位机的时候int就是占16位的)。

顺序表:各个变量存储在相邻的内存空间,就是大家都挨着住。

在这里插入图片描述

物理地址都可以通过数据的类型推算出来,比如刚说的int类型,上图的c就是4,因为一个int四个字节嘛 (PS:计算机寻址最小单位为字节)

python的列表就是顺序存储的。lst = [22 , 42 , 125 , 6]
但是,list是可以存放不止一种数据类型的,比如:lst = [22 , “abc” , 35 , 78.6]
那么问题来了,上述图(基本布局)关于地址的计算方法不再适用了,因为每个数据类型占用的字节数不同,无法方便的计算出列表某一元素的地址。

这便要引出元素外置的顺序表,下图形象的描绘了含有不同数据类型列表中获取元素的过程。

简单来说就是,地址的地址。虽说各个元素的地址无规律可循,但是至少这些地址都是整型数据吧,那就把这些地址存储到连续的地址里,这样获取元素的时候,就是先基于lst[0]地址的地址,推算出要求的元素的地址的地址,然后就能一路找到元素本身啦

在这里插入图片描述

顺序表真正存储的时候还会增添一个表头信息的
顺序表有两种基本的实现方式:一体式和分离式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值