3. 數組和列表

先說基本的線性結構,經常使用的就是線性結構,也是比較簡單的,特色以下: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

image.png


append:


操做 內存分配策略 平均時間複雜度
init[] *  pylistobj O(1)
append(0)

image.png
append(0)會分配4個pylistobj,不會一次只分配一個,會佔用空間

當分配足夠的空間,時間複雜度是O(1),不然它就會從新開闢並拷貝原來的數據到新開闢的空間中去,這時就會退化,時間複雜度是O(n)
append(1) image.png
append(2) image.png
append(3)

image.png

append(4)

image.png當超出它的大小限制的時候,會進行一個resize的操做,由於不夠裝了,因此從新分配8個空間

























insert:

insert

insert 通常會往中間插入,這樣會比較耗費時間,會從新進行內存分配,好比insert一個元素 -1,這時就要從新開闢空間,總長度就變成了16

image.png
數組的容量稱爲capacity(總內存分配的容量),而length指的是有多少個元素,好比以前append了5個元素,insert一個-1,這時length就是6,即6個元素,而capacity是16,因此insert操做會從新的去分配,因此他的時間複雜度平均下來是O(n)

O(n)


pop:

pop

pop默認是移除最後一個元素,因此時間複雜度是O(1)

image.png
由於只是要把第5位指針往前面移動一位,這時length的長度變成5個,時間複雜度O(1);

但若是從中間進行pop的時候,這樣就會把後面的元素往前移,這時候時間複雜度就會退化,變成O(n).

O(1)

O(n)


remove:

remove

image.png
加入要把中間的元素刪除掉,要把後面的每個元素全都往前移,這時候的時間複雜度是O(n)

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

相關文章
相關標籤/搜索