1. 程式人生 > >詳解python中list的實現技術-分離式動態順序表!

詳解python中list的實現技術-分離式動態順序表!

這是python-list的官方實現方式,但其中關於分離式動態順序表的實現方式描述的不夠細緻,如果你有資料結構基礎的話可以直接去看這篇部落格,如果沒有的話不妨先看看這篇!

什麼事順序表?

  • 將元素順序地存放在一塊連續的儲存區裡,元素間的順序關係由它們的儲存順序自然表示。
  • 但是上面的解釋可能還不夠明確,大家可以嘗試這樣理解:
  • 在程式中,經常需要將一組(通常是同為某個型別的)資料元素作為整體管理和使用,需要建立這種元素組,用變數記錄它們,傳進傳出函式等。一組資料中包含的元素個數可能發生變化(可以增加或刪除元素)。
  • 對於這種需求,最簡單的解決方案便是將這樣一組元素看成一個序列,用元素在序列裡的位置和順序,表示實際應用中的某種有意義的資訊,或者表示資料之間的某種關係。
  • 這樣的一組序列元素的組織形式,我們可以將其抽象為線性表。一個線性表是某類元素的一個集合,還記錄著元素之間的一種順序關係。線性表是最基本的資料結構之一,在實際程式中應用非常廣泛,它還經常被用作更復雜的資料結構的實現基礎。

根據線性表的實際儲存方式,分為兩種實現模型:
順序表,將元素順序地存放在一塊連續的儲存區裡,元素間的順序關係由它們的儲存順序自然表示。
連結串列,將元素存放在通過連結構造起來的一系列儲存塊中。

瞭解了順序表的實現方式,接下來我們聊聊什麼事分離式動態順序表:
在這裡插入圖片描述

  • 首先看順序表a,也就是左側的順序表,再看這張圖之前,大家要了解兩個概念,邏輯地址與實體地址。
  • 邏輯地址指的就是當你想使用你儲存在記憶體中的元素時,你引用(也可以稱為索引)他的一種方式,舉個列子,大家經常使用的list[index],這裡的index就是邏輯地址。
  • 實體地址當你想要把一個列表儲存到計算機時,cpu會在記憶體中為你開闢一塊連續的地址(這裡的地址即實體地址),舉個列子:
    a = [1,2,3] 這裡我們建立一個a列表,裡面儲存了1,2,3三個元素,那麼他們是如何儲存在記憶體中的呢?
    在這裡插入圖片描述
    其實a指向的就是紅色的那一塊區域,那麼有人會問了,為什麼我的列表裡只有1,2,3你卻儲存了三個元素呢?
    其實這種設計機制,是為了你使用的時候方便,在紅色框內,紅色的數字1,2,3是列表中要儲存的元素,最上面的三個資料時列表的頭資訊,他們分別儲存的是,elemcount(元素個數),max(最大元素),min(最小元素),之所以儲存這些資訊是為了不用每一次訪問這個列表是都要遍歷一遍列表,節省了時間。
    而圖最左側的綠色框內,就是實體地址了。
    大家有沒有想過為什麼列表可以[index]索引呢?

    其實道理很簡單,當你建立列表時,你會向記憶體申請一串連續的地址,那麼當你得到第一個元素的實體地址時,你是不是就可以很輕鬆得把其餘的元素都找到呢?
    很簡單的一個定址公式:Loc(ei) = Loc(e0) + c*i
    loc(ei)指的是你要尋找的元素的實體地址,loc(e0)指的是第一個元素的地址,c指的是列表中每個元素所佔位元組數,i指的就是元素在列表中的下標。

說完了實體地址,那我們來說說什麼是分離式動態順序表:
如果你在儲存是總把元素與表頭資訊放在一起的話,會發生什麼,卻是你在使用時會很方便,索引很快尋找很方便,但是當你要擴大列表,甚至是改變其中元素型別呢,你不單單是想在列表中儲存資料那麼簡單了,你想存字串,甚至是物件的時候,那麼這種儲存方法顯然會給你的計算機帶來很大的負擔,我們都知道,a = 1,a其實並沒有指向1,a只是指向了1在記憶體中的實體地址,那麼試想我們是不是也可以,讓列表中的下標們也指向,元素們在記憶體中的實體地址呢?
在這裡插入圖片描述
這種儲存方式就是所謂的元素外接了(也成為分離式),這種儲存方式會大大,減少記憶體的負擔。
說完了分離式再來說說什麼是動態順序表,其實這個動態很好理解,在講實體地址的時候我說在列表的表頭資訊裡,會儲存當前列表的元素個數,那麼當你在執行插入操作時,列表會自動的去給你擴容,即換一塊更大的儲存區域,這也就是所謂的動態了。