先說基本的線性結構,經常使用的就是線性結構,也是比較簡單的,特色以下: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) | 當超出它的大小限制的時候,會進行一個resize的操做,由於不夠裝了,因此從新分配8個空間 |
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