數據結構學習——02—順序表

Python代碼執行步驟:
當我們寫好python的代碼的時候,此時需要使用CPython/GPython這樣的解釋器(不是IDE的編譯器)進行解釋成010101這樣的二進制數據,再讓CPU執行。

內存中一個int類型在32位的系統中佔用4個字節,
內存中的單位是字節,1個字節佔8位。
所以int=1的在內存中的表示方法是:

每多1個字節,地址+1

地址:0x01 00000000
地址:0x02 00000000
地址:0x03 00000000
地址:0x04 00000001

1個char類型佔用1個字節,相當於1個int類型可以被4個char類型表示。

舉例:int =1,2,3 -------將這一組數據看作連續的整體進行存儲在內存中

0x01 1
0x05 2
0x09 3

注意內存地址欄的變化
在這裏插入圖片描述
數組要從0開始編號,不是從1:
從數組存儲內存模型上看,“下標”最確切的定義應該是“偏移(offset)”。用a來表示數組的首地址,a[0]就是偏移爲0的位置,也就是首地址,a[k]就表示偏移k個type_size的位置,所以計算a[k]的內存地址只需要用這個公式:
a[k]_address = base_adress + k * type_size

列表中的數據結構一樣的時候,直接存儲爲基本順序表
列表中的數據結構不一樣的時候,存儲爲元素外置順序表

例如:li=[12,‘ab’,1.11,100]
在這裏插入圖片描述
此時數據類型不同,內存中讀取數據的時候,是根據li找到上圖中的0x324,0x328,0x332,0x336這樣的首地址,這幾個地址中存儲的也是地址,就是0x100,0x200,0x300,0x400這樣的地址,這些地址是指向li中的實際需要讀取的數據,因爲地址0x100,0x200,0x300,0x400這樣的地址佔用的四個字節是相同,他們的地址可以連續。
在這裏插入圖片描述
順序表:將元素順序地存放在一塊連續的存儲區裏,元素間的順序關係由它們的存儲順序自然表示。
順序表的結構:
在這裏插入圖片描述
一個順序表的完整信息包括兩部分,一部分是表中的元素集合,另一部分是爲實現正確操作而需記錄的信息,即有關表的整體情況的信息,這部分信息主要包括元素存儲區的容量和當前表中已有的元素個數兩項。
在這裏插入圖片描述
舉例:下圖中的最左邊是一體式結構的順序表,中間的是新創建的一體式結構的順序表,最右邊的是分離式結構的順序表,分離數據表中最重要的區別是表頭部分中包含有存儲數據的初始數據的首地址信息,即圖中的0x111就是數據的存儲中的200的內存地址。
當需要修改一體式結構的順序表中的數據的時候,我們需要重新申請內存中的一個空間,重新創建一個新的首地址才行;而分離式順序表,只需要修改一下新添加的數據的地址信息在表頭部分,表頭元素個數信息更新即可,不需要重新申請內存空間。
所以python中的list類型數據進行更改的時候,原始數據的id信息不會更改,因爲採用的是分離式順序表的數據結構。
在這裏插入圖片描述
元素存儲區替換
一體式結構由於順序表信息區與數據區連續存儲在一起,所以若想更換數據區,則只能整體搬遷,即整個順序表對象(指存儲順序表的結構信息的區域)改變了。

分離式結構若想更換數據區,只需將表信息區中的數據區鏈接地址更新即可,而該順序表對象不變。

元素存儲區擴充
採用分離式結構的順序表,若將數據區更換爲存儲空間更大的區域,則可以在不改變表對象的前提下對其數據存儲區進行了擴充,所有使用這個表的地方都不必修改。只要程序的運行環境(計算機系統)還有空閒存儲,這種表結構就不會因爲滿了而導致操作無法進行。人們把採用這種技術實現的順序表稱爲動態順序表,因爲其容量可以在使用中動態變化。

擴充的兩種策略

每次擴充增加固定數目的存儲位置,如每次擴充增加10個元素位置,這種策略可稱爲線性增長。
特點:節省空間,但是擴充操作頻繁,操作次數多。
每次擴充容量加倍,如每次擴充增加一倍存儲空間。
特點:減少了擴充操作的執行次數,但可能會浪費空間資源。以空間換時間,推薦的方式。

順序表的增刪操作
在這裏插入圖片描述在這裏插入圖片描述
Python中的順序表
Python中的list和tuple兩種類型採用了順序表的實現技術,具有前面討論的順序表的所有性質。

tuple是不可變類型,即不變的順序表,因此不支持改變其內部狀態的任何操作,而其他方面,則與list的性質類似。

list的基本實現技術
Python標準類型list就是一種元素個數可變的線性表,可以加入和刪除元素,並在各種操作中維持已有元素的順序(即保序),而且還具有以下行爲特徵:
基於下標(位置)的高效元素訪問和更新,時間複雜度應該是O(1);
爲滿足該特徵,應該採用順序表技術,表中元素保存在一塊連續的存儲區中。

允許任意加入元素,而且在不斷加入元素的過程中,表對象的標識(函數id得到的值)不變。
爲滿足該特徵,就必須能更換元素存儲區,並且爲保證更換存儲區時list對象的標識id不變,只能採用分離式實現技術。

在Python的官方實現中, list就是一種採用分離式技術實現的動態順序表。
這就是爲什麼用list.append(x) (或 list.insert(len(list), x),即尾部插入)比在指定位置插入元素效率高的原因。

在Python的官方實現中,list實現採用瞭如下的策略:在建立空表(或者很小的表)時,系統分配一塊能容納8個元素的存儲區;在執行插入操作(insert或append)時,如果元素存儲區滿就換一塊4倍大的存儲區。但如果此時的表已經很大(目前的閥值爲50000),則改變策略,採用加一倍的方法。引入這種改變策略的方式,是爲了避免出現過多空閒的存儲位置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章