python列表大小有限度么_Python高性能计算之列表

接下里的系列文章中,我们将讲一下Python高性能计算,如何提高Python的计算性能?有哪些好用的库?请持续关注我们。第一节我们先来讲列表。

Python列表是有序的元素集合,在Python中是使用大小可调整的数组实现的。数组是一种基本的数据结构,由一系列连续的内存单元组成,其中每个内存单元都包含指向一个Python对象的引用。

列表在访问、修改和增加元素方面,速度都非常快。其中访问和修改元素,都需要从底层数组的相应位置获取对象引用,因此其复杂度是O(1)。增加元素的话,跟C++中的Vector原理类似(C++ vector用法详解),当创建一个空列表时,将分配一个长度固定的数组;当在列表末尾插入元素时,复杂度为O(1),数组中的位置逐渐被填满。当所有位置都被占据后,列表需要增大其底层数组的长度,进而触发内存的重新分配,这需要的时间为O(N)。但内存分配的操作并不频繁,因此在列表尾部增加元素的时间复杂度接近于O(1).

在列表开头或中间增加或删除元素的效率就要慢很多了,这也很容易理解,后续所有的元素都要移动一个位置,所以时间复杂度是O(N)。因此,列表的几个常规操作的时间复杂度如下:

操作

时间复杂度

list.pop()

O(1)

list.pop(0)

O(N)

list.append(1)

O(1)

list.assert(0, 1)

O(N)

在某些场景下,我们需要频繁的对列表的头和尾进行操作,这时我们就可以使用双端队列collections.deque,这种数据结构被设计成能够在集合两端高效地增加和删除元素,在Python中,双端队列是以双向链表的方式实现的。deque的常用操作如下:

31e086a7854a12663c301ab9d628c47b.png

image-20201115151353509

IPython中的示例代码如下:

from collections import deque

d = deque(range(10))

>>> deque([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

d.pop()

>>> 9

d.popleft()

>>> 0

d

>>> deque([1, 2, 3, 4, 5, 6, 7, 8])

d.rotate(2)

>>> deque([7, 8, 1, 2, 3, 4, 5, 6])

deque操作头和尾的时间复杂度都是O(1).

操作

时间复杂度

deque.pop()

O(1)

deque.popleft()

O(1)

deque.append()

O(1)

deque.appendleft()

O(1)

虽然deque操作头和尾的时间复杂度都是O(1),由于list,但我们平时却不太会使用双端队列。主要是因为除了头和尾,访问双端队列中间的元素所需的时间为O(N)。

list和deque访问

时间复杂度

list[0]

O(1)

list[N/2]

O(1)

list[N-1]

O(1)

deque[0]

O(1)

deque[N/2]

O(N)

deque[N-1]

O(1)

列表查找元素通常是一种O(N)操作,使用list.index()来完成。为了提高列表的查找速度,一种简单的办法是确保底层数组是有序的,并使用模块bisect来执行二分查找。

import bisect

lst = [10, 11, 13, 14]

bisect.bisect(lst, 12)

>>> 2

bisect.bisect(lst, 13)

>>> 3

可以看到,使用bisect可以直接得出这个值应该插在什么位置,如果该值(13)本来就在列表中,默认返回的位置是列表中该元素后面的位置(3)。当然我们可以使用bisect_left函数,这样可以返回该元素前面的位置。

bisect.bisect_left(lst, 13)

>>> 2

bisect.bisect_right(lst, 13)

>>> 3

bisect是使用二分法查找,时间复杂度是O(log(N)),在数据量较大时,比list.index()的O(N)复杂度要节省出不少的时间。

微信:xhclsys2

欢迎关注微信公众号:Quant_Times

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值