04_線性表_順序表


1、線性表簡介

在程序中,經常需要將一組(通常是同為某個類型的)數據元素作為整體管理和使用。最簡單的解決方案便是將這樣一組元素看成一個序列,用元素在序列里的位置和順序,表示實際應用中的某種有意義的信息,或者表示數據之間的某種關系。我們將其抽象為線性表。

根據線性表的實際存儲方式,分為兩種實現模型:

  • 順序表,將元素順序地存放在一塊連續的存儲區里,元素間的順序關系由它們的存儲順序自然表示。
  • 鏈表,將元素存放在通過鏈接構造起來的一系列存儲塊中。

2、順序表怎樣存儲

下面我們將著重于順序表。
還記的上一節的內存嗎?
順序表,作為一種存儲結構,他需要在內存中申請空間進行存儲,而它的特點就是必須要連續存儲,也就是要拿出連號的‘柜子’進行存儲,那么雖然內存有很多存儲空間,但在其連續的空間內,可能有局部內存已經被其他東西占用,

0x03 0x04 XXXX
0x06 0x07 0x08
XXXX 0x10 0x11

假設我們拿出了03、04兩個柜子進行存儲,但是我們現在需要三個柜子來存儲,而05的位置已經被占用,這時候,我們就要吧03、04柜子里的東西重新拿出來,再找一個三個連續的柜子放進去,比如06~08的位置,此時,如果我們又要存儲別的東西,就又要重新找滿足要求的連續的“柜子”。這就是順序表的存儲特性,不過為了避免經常“搬遷”,采用一中策略:提前開辟更多的位置來等待你存儲,如果滿了,那么就再去新開辟二倍的空間,滿了再二倍,當然也會有個界限,否則就造成空間浪費了。


3、從0開始
0x03 1 0x04 2
0x05 3 0x06 4

li = [1, 2, 3, 4]
假設我們在一塊連續的位置存儲了數組li,那么取li[0]的時候, 就是先找到li所在的地址Ox03, 然后從這個地址讀取4個字節(因為是整型), 如果是取li[3], 也是先找到li所在的地址Ox03,再往后跳過三個數據類型字節的位置, li[3] = Ox03 + 3*4Btye所以li[0]的**0 **的意思就是偏移量,所以數據是從零開始。


4、元素外置的順序表

上面介紹的是基本的順序表,就是存儲的空間里都是類型相同的數據,那么你可能會問了,明明在Python中數組里存儲的可以是任何類型的數據。這時候,我們就要寄出元素外置的順序表了,這是個什么意思呢?其實這種存儲不同類型數據的數組,其本身并沒有把那些數據存儲在自己的空間里,而是把這些數據對應的地址存在了自己的空間里,這樣自己空間里還是類型一致的數據。

假如還是上面的那塊地址,

0x03 0x10 0x04 0x31
0x05 0x52 0x06 0x43

這次在這里存儲的是四個內存地址,而這些地址又對應相應的數據。

0x10 ‘abb’ 0x31 233
0x52 {1, 2} 0x43 {'ha':'ho'}

這時候我們在訪問li[0]的時候將進行已下操作:
首先找到li所對應的地址Ox03, 再通過這個地址存儲的地址Ox10 找到數據'abb', 這種存儲地址的地址空間連續稱作數據外置表, 可以通過列表存儲不同類型的數據。


5、順序表的實現

這里Python已經內置,但我們來考慮自己如何實現順序表。

順序表的兩種基本實現方式

除了需要數據部分, 還需要表頭信息用來存儲表的大小以及已存儲數據量。
a> 一體式結構:把表頭信息和數據區連續存儲
b> 分離式結構:把表的大小與已存儲量以及存儲地址放到一個地方, 地址指向另一塊存儲位置

優劣問題,數據存儲問題:

連續: 讀取方便, 當存儲數據超過預先支配的大小, 那就需要重新申請一塊連續空間, 進行數據搬遷, 釋放老的空間, 表頭也需要改變, 起始地址就會改變。

分離: 間接讀取,當存儲數據超過預先支配的大小, 只需要改變存儲的地址, 并不需要改變表頭的位置。

當存儲空間不足的時候,擴充帶來的問題: 擴充預留多少大小。
下面有兩種解決策略。
兩種策略:
1> 每次申請擴充固定數目的位置, 每次都擴充10個空間,
特點: 節省空間, 但是擴充操作頻繁, 操作次數多
2> 每次申請都擴充倍數, 4->8->16->32
特點: 空間換取時間

允許擴充的順序表叫做動態順序表, 位置不夠了可以取擴充位置


6、順序表操作:

增加元素:

a>表尾端加入元素
b>非保序的元素插入
c>保序的元素插入

a>O(1)
b>直接把需求位置的數據放到尾端, 再把數據放入改位置,不常見, O(1)
c>O(n), 需要把所有數據往后移一位, 才能在空位加入元素

刪除元素:
a>刪除表尾元素 O(1)
b>非保序元素刪除 O(1) 刪除元素, 把末尾填入空位
c>保序刪除 O(n) 刪除元素在把每位上移


7、Python中的順序表:list和tuple

a>按下表位置索引:復雜度O(1)
b>允許加入任意元素, 表對象標識(id地址)不變:表頭和數據區分離式存儲
c>可以存儲不同類型的數據:元素外置方式

擴充策略:
建立空表(或很小的表), 系統分配一塊能容納8個元素的存儲區, 進行插入時, 如果存儲器滿了, 存儲區就換一塊4倍大的存儲區, 但是此時表已經很大(閥值50000),則改變策略,采用加一倍的方法, 避免出現過多的空閑位置


小結

1、順序表屬于線性表的一種。
2、從0開始。
3、存儲同樣類型的數據。不同數據是如何存儲的?
4、怎么構造的?都有什么優劣?
5、添加和刪除元素的復雜度?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 關于Mongodb的全面總結 MongoDB的內部構造《MongoDB The Definitive Guide》...
    中v中閱讀 32,010評論 2 89
  • 在一生當中,我們會經歷很多波折,在期間有很多讓人感動的力量時刻在催促我們不停向前。去年在接上幼兒園兒子回家時就讓我...
    高天明月55閱讀 186評論 1 1
  • 你說你跋山涉水只為見我。 你躲避了暴風雨,看過了太多塵世繁華,歷經了春夏秋冬。 你覺得我是這世上唯一的美好,其實你...
    珂先生啊喂閱讀 291評論 0 3
  • 鄉間有田雨,今生有余歡。 繁華(huā)秋第時,娘子欲還(huán)家。
    伯文閱讀 328評論 0 1