連結串列(python)

清減幾分發表於2020-08-10

一、連結串列和陣列

在編寫程式碼中,我們儲存的資料是儲存於記憶體當中,記憶體就像一塊塊並列排序的小方盒,每個小方盒都有自己地址,我們儲存的資料就在這樣一個個小方盒當中。

                連結串列(python)

這些資料存放的結構有兩種基本方式,陣列和連結串列。

1,陣列

陣列在記憶體中是按順序,記憶體地址來儲存的,就好似上圖的抽屜,從上到下,按順序存放物品。這一特徵也就意味著資料在記憶體中是相連的,緊緊不分開的,小的記憶體空間可能會裝不下較多的資料,造成了記憶體空間浪費。

世界上許多事情有好有壞,有利有弊,陣列也是如此,資料在記憶體中緊密相連,也就意味著牽一髮而動全身,比如你想在陣列中新增一項資料,這就好比一排已經排好隊的士兵,每個人都有自己的編號,而此時你突然要插入其中。

你:“兄弟方便讓個位置嗎?”

你後面的士兵都一臉凶神惡煞地看著你,如果不是排長強力要求你插入其中,他們肯定不會讓你入隊,因為你的入隊,讓你身後的士兵的編號都要往後挪。

陣列也是一樣,當新加入一個資料時,這就意味著它後面的資料記憶體地址都要往後稍一稍,刪除亦如此。

 

連結串列(python)

2,連結串列 和賦值原理

連結串列和在記憶體中排列整齊的陣列不同,它們像一堆散兵遊勇,散佈於記憶體中,只要哪裡有空隙就往哪裡鑽,連結串列高效地運用了記憶體空間。雖然它們看起來雜亂無章,但其實它們井然有序,暗號讓它們緊緊相連。資料與資料之間有一條“暗號”的鏈子相連線,那個資料在首位,那個資料在第二位……在末尾都非常清楚。

這種“暗號”其實就是記憶體地址,如下圖,長方形就是節點,一個節點包含了兩個方面的內容,資料和“暗號”,這個“暗號”其實就是下一個節點的引用資訊。

 

連結串列(python)

連結串列的第一個和最後一個節點最重要和最特殊,最後一個節點則意味著後面沒有資料了,所以它指向None,第一個節點的記憶體地址需要一個地方來儲存,所以設立一個head屬性對第一個節點應用。

下面來實現節點程式碼,一個節點需要存放資料和對下一個資料的引用:


class Node:
def __init__(self,x):
self.data = initdata #存放資料
self.next = None #對下一個節點的引用

def getData(self): #返回資料
return self.data

def getNext(self): #返回下一個節點
return self.next

def setData(self,newdata):
self.data = newdata

def setNext(self,newnext):
self.next = newnext
 

相信很多人都有疑問,為什麼把下一個節點賦給上一個節點的next就實現了記憶體的引用呢?這與Python的特性有關,Python沒有專門的指標,所有變數即是指標。

舉一個例子,a = 6,一個簡單的賦值,它在記憶體中是怎樣實現的呢?

首先在記憶體中會建立資料6,資料6在記憶體中有自己的記憶體地址,然後再把變數標籤a指向6,如上圖a這個長方形中,實際是資料6的記憶體地址。再比如,a,b = b,a,  這實際就是a指向原來b指向的地址,b指向原來a指向的地址。明白了記憶體中賦值的原理,那麼對Python連結串列中,next  = 下一個節點,就會很清晰了,next指向下一個節點的記憶體地址。

三,單連結串列的實現

1,連結串列的優點和缺點

連結串列插入和刪除資料非常快,但讀取資料非常慢

  陣列 連結串列
讀取 O(1) O(N)
插入 O(N) O(1)
刪除 O(N) O(1)

 

陣列的讀取非常快,因為它在記憶體中連續儲存,插入和刪除慢,是因為插入和刪除都要改變相應的記憶體地址。

連結串列的插入和刪除都很快,因為只要相應的改變節點中next的指向即可,連結串列訪問一個特定資料時,必須沿著連結串列一個一個資料訪問,所以讀取很慢、

2,連結串列的方法

from node import Node
class UnorderedList:

    def __init__(self):
        self.head = None

    def add(self,item): #新增資料
        temp = Node(item)
        temp.setNext(self.head) #next指向表頭,head為引用表頭的資訊
        self.head = temp  #在把head指向新增加的節點

    def size(self):  #返回連結串列的size
        current =self.head
        count = 0
        while current != None:
            count +=1
            current = current.getNext()

        return count

    def search(self,item):  #資料是否在連結串列中
        current = self.head
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()

        return found


    def remove(self):   #刪除某個資料
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData == item:
                found = True
            else:
                previous = current
                current = current.getNext()

        if previous == None:
            self.head = current.getNext()

        else:
            previous.setNext(current.getNext())

 

相關文章