天天看點

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

一、數組

1、數組的定義

數組是由類型相同的資料元素構成的有序集合,每個元素稱為數組元素,每個元素受 n(n>=1) 個線性關系的限制,每個元素在 n 個線性關系中的序号i1, i2, …,in 稱為該元素的下标,可以通過下标通路該資料元素。

數組分為一維數組和多元數組。

數組一旦被定義, 它的維數和維界就不再改變。 是以, 除了結構的初始化和銷毀之外, 數組隻有存取元素和修改元素值的操作。

1.1、一維數組

一維數組是指下标的個數隻有一個的數組, 有時稱為向量, 是最基本的資料類型, 在Java 中需要事先聲明,程式才能夠在編譯過程中預留記憶體空間。

聲明的格式一般為:

<資料類型><變量名稱>[]= new<資料類型>[<數組大小>];      

例如:

float numbera=new int[5];      

聲明一個長度為 5 的浮點資料類型的一維數組,數組名為numbera。

1.2、多元數組

多元數組是指下标的個數有兩個或兩個以上, 我們比較常用的是二維數組。

二維數組的聲明同一維數組。 格式為:

<資料類型> <數組名稱>[][]=new 〈資料類型>[sizel][size2];      
int data[][]=newim [5][4];      

表示聲明了名稱為data的整形二維數組。

2、數組存儲

2.1、一維數組的存儲

一維數組A[n] = {a0, a1…,an-1}的資料存儲按照順序存儲, 邏輯位址和實體位址都是連續的。

一維數組任意資料元素ai的存儲單元位址:Loc(ai) = Loc(a0) + i * k (0 ≤ i < n),其中k為單個元素所占空間。

2.2、多元數組的存儲

由于記憶體是一維的,而數組是多元結構,可以認為二維數組是一個每個資料元素是一維數組的一維數組;三維數組是每個資料元素是二維數組的一維數組;四維數組是個每個資料元素是三維數組的一維數組,以此類推。

以二維數組的順序存儲為例說明, 對于一個m×n的二維數組,可以看成一個矩陣:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

也可以看成一個行向量的一維數組:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

二維數組在順序存儲時一般有兩種。

  • 行優先順序: 存儲時先按行從小到大的順序存儲, 在每一行中按列号從小到大存儲。
重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表
  • 列優先順序: 存儲時先按列從小到大的順序存儲, 在每一列中按行号從小到大存儲。
    重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

以上的兩種存儲順序中, 第一個被存放的元素總是第一行第一列的資料元素, 是以該元素的位址是我們的己知條件。

行優先順序存儲二維數組的任一資料元素 a[i,j] 的存儲單元位址:Loc(a[i,j]) = Loc(a[0, 0]) + (i * n + j) *k (0 ≤ i < m,0 ≤ j < n),其中k為單個元素所占空間。

列優先存儲的二維數組a[i,j]的存儲單元位址:Loc(a[i,j]) = Loc(a[0,0]) + (j * m + i)*k(0 ≤ i < m,0 ≤ j < n),其中k為單個元素所占空間。

二、矩陣的存儲

1、矩陣的壓縮存儲

所謂矩陣的壓縮存儲, 也就是在存儲數組時, 盡量減少存儲空間, 是以在矩陣存儲中, 如果有規律可尋, 隻要存儲其中一部分, 而另一部分的存儲位址可以通過相應的算法将它計算出來, 進而占有比較少的存儲空間達到存儲整個矩陣的目的。

矩陣的壓縮存儲僅是針對特殊矩陣的, 而對于沒有規律可循的二維數組則不能夠使用矩陣壓縮存儲。

二維數組(矩陣)的壓縮存儲一般有 3 種, 它們分别是對稱矩陣、 稀疏矩陣和三角矩陣。

1.1、對稱矩陣

若n階矩陣A中的元素滿足以下條件:

aij=aji(i>=1;j>=1)

則成為對稱矩陣。如下例:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

結合資料結構壓縮存儲的思想,我們可以使用一維數組存儲對稱矩陣。由于矩陣中沿對角線兩側的資料相等,是以數組中隻需存儲對角線一側(包含對角線)的資料即可。

對稱矩陣的實作過程是,若存儲下三角中的元素,隻需将各元素所在的行标 i 和列标 j 代入下面的公式:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

存儲上三角的元素要将各元素的行标 i 和列标 j 代入另一個公式:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

最終求得的 k 值即為該元素存儲到數組中的位置(矩陣中元素的行标和列标都從 1 開始)。

例如,在數組 skr[6] 中存儲上文中的對稱矩陣,則矩陣的壓縮存儲狀态如圖 所示(存儲上三角和下三角的結果相同):

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

注意,以上兩個公式既是用來存儲矩陣中元素的,也用來從數組中提取矩陣相應位置的元素。例如,如果想從上圖中的數組提取矩陣中位于 (3,1) 處的元素,由于該元素位于下三角,需用下三角公式擷取元素在數組中的位置,即:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

1.2、稀疏矩陣

稀疏矩陣是矩陣中的一種特殊情況,其非零元素的個數遠小于零元素的個數。

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

稀疏矩陣壓縮存儲主要采用三元表示法來實作。其存儲規則是每一個非零元素占有一行, 每行中包含非零元素所在的行号、 列号、 非零元素的數值。

(row col value)

例如稀疏矩陣:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

采用三元表示法:

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

1.3、三角矩陣

以對角線劃分,三角矩陣有上三角和下三角兩種。

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

主對角線下的資料元素全部相同的矩陣為上三角矩陣,主對角線上元素全部相同的矩陣為下三角矩陣。

對于這類特殊的矩陣,壓縮存儲的方式是:重複元素C可共用一個存儲空間,其餘的元素可以采用對稱矩陣的壓縮存儲方式存儲。

這麼一來,對稱矩陣可以看做一種特殊的三角矩陣。

三、廣義表

1、廣義表的定義

廣義表是線性表的推廣, 具體定義為n(n>=0)個元素的有限序列。

一般記作:LS=(a1,a2,a3, … ai, …, an)

廣義表的資料元素可以分為兩種,一種不可再分(原子),一種可再分(子表)。

以下是一些常見的廣義表定義:

  • A = ():A 表示一個廣義表,隻不過表是空的。
  • B = (e):廣義表 B 中隻有一個原子 e。
  • C = (a,(b,c,d)) :廣義表 C 中有兩個元素,原子 a 和子表 (b,c,d)。
  • D = (A,B,C):廣義表 D 中存有 3 個子表,分别是A、B和C。這種表示方式等同于 D = ((),(e),(b,c,d)) 。
  • E = (a,E):廣義表 E 中有兩個元素,原子 a 和它本身。這是一個遞歸廣義表,等同于:E = (a,(a,(a,…)))。

從上面的例子可以歸納出一些結論:

  • 廣義表的元素可以是子表, 而子表的元素還可以是子子表……由此, 廣義表是一個多層次的結構。
  • 廣義表可為其他廣義表共享。
  • 廣義表可以是一個遞歸表,即廣義表也可以是其本身的一個子表。

當廣義表不是空表時,稱第一個資料(原子或子表)為"表頭",剩下的資料構成的新廣義表為"表尾"。

2、廣義表的存儲

由于廣義表中的資料元素具有不同的結構,通常是一種遞歸的資料結構,很難為每個廣義表配置設定固定大小的存儲空間,一般用鍊式存儲結構表示,有頭尾表示法和孩子兄弟表示法兩種存儲方式。

2.1、頭尾表示法

任意非空的廣義表,可分解為表頭和表尾,反之,一對确定的表頭和表尾可唯一确定一個廣義表。

在頭尾表示法中需要有兩種結構的結點:一種是表結點,可以表示字表;一種是原子結點,用來表示原子。

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表
重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

在表結點中有三個域組成:标志域、指向表頭的指針域和指向表尾的指針域;

而原子結點需要兩個域:标志域和值域。标志域是用來區分這兩種結點的。

2.3、孩子兄弟表示法

在孩子兄弟表示法中,原子結點和表結點用相似的兩種結點來表示。

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表

其中表結點有孩子結點,cp和bp分别指向第一個孩子換一個兄弟的指針域;

原子結點是無孩子結點,data和bp分别是指域和指向兄弟的指針域。

tag是标志域,用來區分這兩類結點,如tag為1,則表示該結點為表結點即有孩子的結點;tag為0,則表示該節點為原子結點即無孩子結點。

重學資料結構(四、數組和廣義表)二、矩陣的存儲三、廣義表