Python的list
(1)list是一种线性结构,可看作线性表的一种实现。
重要特点:基于下标(位置)的元素访问和更新操作,复杂性为O(1),允许任意加入元素(不会出现“表满”而无法加入新元素的情况),而且在不断加入元素的过程中,表对象标识( id(...). 的值)不变
(2)list实现的基本约束和解决方案
要求O(1)的元素访问并维持元素的顺序,只能采用连续表技术,元素保存在一块连续存储区
要能容纳任意多元素,必须在元素个数将要超出存储区容量时换一块更大存储区。要想在替换存储时id 不变,只能采用分离式实现
(3)采用上述实现方法,自然的后果:
一般的元素加入/删除都需要O(n) 时间,需要移动许多元素。
如果要求加入元素时存储区已满,就需要换一块存储, 把原有元素拷贝过去(优化: 可以在拷贝过程中完成元素加入)
list 的逐步建立
(1)较大的list ,通常是通过不断加入元素逐步建立起来的。
加入一个元素,一般情况需要0(m) 时间
建立起n个元素的表,就需要O(m2) 时间
最好的情况:尾端加入,不需要移动元素
(2)注意,不断在尾端加入元素的过程中可能出现两种情况
如果存储区不满,O(1) 时间可以完成操作
如果存储区满,就需要O(u) 时间(换存储区,拷贝元素)
最坏情况复杂性一定是O(m), 但能否得到较好的平均时间?
(3)情况:如果高开销操作很少出现,平均操作代价可能比较低。
考虑每次替换存储区增加10 个空位,10 次加入才有一次高代价
但注意,(1/10) O(n) = O(n),平均复杂性的性质没变。
(4)list里元素越多(表越长),换一次存储区的代价也越高
要想平均结果较好,随着表长度增加,换存储区的频度应降低
一种可能做法:每次换存储区时,容量加倍
(5)计算:假设表的初始容量为1, 不断增长到长度为 100,000
加入操作共做了大约次
替换存储时的元素拷贝:
1+2+4+8+...+ ≈
总开销大约为2*, 是O(m) 的量级,平均O(1)
(6)一次高开销操作后,保证有很多次低开销操作,称为“分期付款式”的常量复杂性(平摊式的复杂性)
Python的list 采用这种设计,因此lst.insert(en(st),x) 比一般位置加入的效率高,等价写法Istappend(x) 。 如合适,应优先使用
list的操作
(1)Python list的实际实现策略
建立空list 时分配可以容纳8个元素的存储区
元素区满时加入:换一块4倍大的存储区;但在表已经比较大时就会改变策略,换存储区时规模加倍
效果:通过尾端加入元素,操作的平均复杂性是0(1)
(2)其他操作的性质由连续表的实现方式确定
所有序列的共性操作,复杂性由操作中需要考察的元素个数确定,其中len() 是O(1) 操作
元素访问和赋值,尾端加入和尾端(切片)删除是0(1) 操作
一般元素加入,切片替换,切片删除,表拼接( extend)等都是O(n)操作。pop操作默认情况是尾端删除返回,为O(1), 一般情
况(指定非尾端位置)为O(n)
(3)Python没提供检查一个list 的当前存储块容量的操作