先说基本的线性结构,经常使用的就是线性结构,也是比较简单的,特色以下:html
内存连续,一开始就会分配一块固定的内存给它,能够经过下标去快速访问经常使用的数组和列表。python
在python 里面有array和list两种git
Array:github
python中array用到的机会没有list多,数组
先演示一下array的用法(https://docs.python.org/2/library/array.html):数据结构
from array import array arr = array('u', 'abcdefg') print (arr[0]) print (arr[3]) print (arr[5])
结果:app
aide
dspa
f3d
缺点也比较明显:
(1)只能存同一种类型,不想list能够在不一样下标存不一样类型的元素;
(2)只能存一些比较基本的数值、字符类型,用得不是不少,通常用numpy里面的array,来作一些数值的处理。
List:
list也是一个线性结构
(1)list的工做过程
经过C解释器代码能够看到是按照 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ....的顺序增加的
https://github.com/python/cpython/blob/master/Objects/listobject.c
append:
操做 | 内存分配策略 | 平均时间复杂度 |
init[] | * pylistobj | O(1) |
append(0) |
|
当分配足够的空间,时间复杂度是O(1),不然它就会从新开辟并拷贝原来的数据到新开辟的空间中去,这时就会退化,时间复杂度是O(n) |
append(1) | ![]() |
|
append(2) | ![]() |
|
append(3) | ||
append(4) |
|
insert:
insert | insert 通常会往中间插入,这样会比较耗费时间,会从新进行内存分配,好比insert一个元素 -1,这时就要从新开辟空间,总长度就变成了16
|
O(n) |
pop:
pop | pop默认是移除最后一个元素,因此时间复杂度是O(1)
但若是从中间进行pop的时候,这样就会把后面的元素往前移,这时候时间复杂度就会退化,变成O(n). |
O(1) O(n) |
remove:
remove |
|
O(n) |
如图:
操做 | 平均时间复杂度 |
---|---|
list[index] | O(1) |
list.append | O(1) |
list.insert | O(n) |
list.pop(index), default last element | O(1) |
list.remove | O(n) |
因此在用list的时候,频繁的进行insert/remove的时候,或是在中间进行pop的话,
可能list就不是一个合适的数据结构,要选用其余更高效的数据结构。
练习:用list实现array的ADT
实现一个定长的数组array的ADT
ps:在其余一些语言中,内置的数组结构就是定长的。
class Array(object): def __init__(self, size=32): self._size = size self._items = [None] * size #定义一个长度为size,元素是none的列表 def __getitem__(self, index): return self._items[index] #定义方法,能够经过[index]进行获取元素 def __setitem__(self, index, value): self._items[index] = value def __len__(self): return self._size def clean(self, value=None): #清空数组 for i in range(len(self._items)): self._items[i] = value def __iter__(self): for item in self._items: yield item #单测(pip install pytest) def test_array(): size = 10 #指定size长度 a = Array() #实例化 a[0] = 1 #set方法 assert a[0] == 1 #get方法 a.clean() #clean方法 assert a[0] is None #clean方法
#pytest array_list.py