數據結構 第9講 數組與廣義表

數據結構 第9講 數組與廣義表

 

數組是由相同類型的數據元素構成的有序集合。

一維數組看一看作一個線性表,例如:


1一維數組

二維數組也可以看作一個線性表,例如:


2二維數組(按列序)

是不是可以看作一個線性表X=(X0X1X2Xn-1)?只不過每一個數據元素Xi也是一個線性表。

那麼,橫看成嶺側成峯:


3二維數組(按行序)

也可以看作一個線性表Y=(Y0Y1Y2Ym-1)?只不過每一個數據元素Yi也是一個線性表。

數組一般採用順序存儲結構,因爲存儲單元是一維的,而數組可以是多維,如何用一組連續的存儲單元來存儲多維數組呢?以二維數組爲例,可以按行序存儲,即先存第一行,再存第二行,…;也可以按列序存儲,先存第一列,再存第二列,…;現在比較流行的C語言,Java都是按行序存儲的。

如果按行序存儲,怎麼找到aij的存儲位置呢?

先看看在存儲aij之前,前面已經存儲了多少個元素:


4二維數組(按行序存儲)

從圖4可以看出,在aij之前一共有i*n+j個元素,如果每個元素用L個字節,那麼需要(i*n+j)*L個字節,只需要用基地址加上這些字節就可以得到aij的存儲位置了。

按行序存儲,aij的存儲位置:

LOC(a00)表示第一個元素的存儲位置,即基地址,LOC(aij)表示aij的存儲位置。

授人以魚不如授人以漁,告訴你記住公式,就像送你一條魚,不如交給你捕魚的祕籍!

存儲位置計算祕籍:aij的存儲位置等於矩陣第一個元素的存儲位置,加上前面的元素個數*每個元素佔的空間數。


如果按列序存儲,怎麼找到aij的存儲位置呢?

先看看在存儲aij之前,前面已經存儲了多少個元素:


5二維數組(按列序存儲)

從圖5可以看出,在aij之前一共有j*m+i個元素,如果每個元素用L個字節,那麼需要(j*m+i)*L個字節,只需要用基地址加上這些字節就可以得到aij的存儲位置了。

按列序存儲,aij的存儲位置:


LOC(a00)表示第一個元素的存儲位置,即基地址,LOC(aij)表示aij的存儲位置。

需要特別注意:二維數組的下標是從1開始的,那麼畫風就變了~~~

在很多科學工程計算問題中,經常遇到一些階數很高的矩陣,而且這些矩陣的很多值是相同的,有的還有很多元素是0,爲了節省空間,可以對這類矩陣進行壓縮存儲。

什麼是壓縮存儲?

把多個相同的元素分配一個存儲空間,元素爲0的不分配空間。

什麼樣的矩陣能夠壓縮?

一些特殊矩陣,如:對稱矩陣,對角矩陣,三角矩陣,稀疏矩陣等。

什麼叫稀疏矩陣?

矩陣中非零元素的個數較少,怎樣纔算是較少呢?一般認爲非零元素個數小於5%的矩陣爲稀疏矩陣。

下面介紹幾種特殊矩陣的壓縮存儲方式:

1.對角矩陣

對角矩陣是指在n´n的矩陣中,非零元素集中在主對角線及其兩側共L(奇數)條對角線的帶狀區域內L對角矩陣。如圖13所示。


13 5對角矩陣

很明顯,L對角矩陣的帶寬爲L,半帶寬d=(L-1)/2,例如5對角矩陣,半帶寬d=2。當|i-j|>d時,aij=0。當|i-j|<=d時,aij≠0,爲對角矩陣的帶狀區域元素。

那麼L對角矩陣一共有多少個非零元素呢?

首先將每一行以對角線爲中心,補零,讓每一行都達到L個元素,如圖14所示。一共補了多少個零呢?第一行補d,第二行補d,…,1,左上角補零個數爲d (d+1)/2,同理,右下角補零個數也爲d (d+1)/2,總的補零個數爲d (d+1),那麼每行按L個元素計算,再減去補零元素個數即可。即帶狀區域元素個數爲:L*n-d (d+1),因爲d=(L-1)/2,即L=2d+1,所有帶狀區域元素個數也可以表達爲:(2d+1)*n-d (d+1)


14 5對角矩陣

那麼,補零後每行都有L個元素,需要L*n個空間。爲了節省空間,第一行前面和最後一行後面的d0可以不存儲,即"掐頭去尾",即需要L*n-2d個空間。如圖15所示,陰影部分就是要存儲的元素。


15 5對角矩陣(掐頭去尾)

如果按行序,用一維數組(下標從零開始)存儲L對角矩陣。

怎麼找到aij的存儲位置呢?

首先找到aii的存儲位置,因爲aii是對角線上的元素,以對角線爲中心,左右兩側都是d個元素,如圖16所示。因此aii之前有i-1行,每行L個元素,aii所在行左側有d個元素,如圖15所示。因此aii之前有(i-1)*L+d個元素,因爲第一行前面的d0"掐頭去尾"沒有存儲,所以aii之前有(i-1)*L個元素。aii的存儲位置爲:(i-1)*L。而aijaii相差j-i個元素,也就是說,aij的存儲位置爲:(i-1)*L+j-i


16對角矩陣存儲(按行序)

總結公式:

按行序,用一維數組(下標從零開始)存儲L對角矩陣,aij的存儲位置:

例如:3對角矩陣,L=3,得到3對角矩陣中aij的存儲位置:k=3(i-1)+j-i=2i+j-3,同樣,5對角矩陣中aij的存儲位置:k=5(i-1)+j-i=4i+j-5

如果一維數組的下標從1開始,公式後面再+1即可。

對角矩陣還有一種按對角線的順序存儲方式,如圖17所示:


圖17 5對角矩陣

即對角線作爲0行,左側分別爲12,…,d行,右側分別爲-1-2,…,-d行,列值不變,相當於轉換爲L×n的矩陣,如圖18所示:


圖18 5對角矩陣存儲(按對角線)

那麼圖18(b)矩陣,其它位置補零,用一維數組(下標從零開始)按行存儲,aij之前有+d行,aij所在行前面有j-1個元素,因此下標爲:



2. 稀疏矩陣

稀疏矩陣是指非零元素個數較少,且分佈沒有規律可言,那麼少到什麼程度纔算稀疏呢?一般認爲非零元素小於5%時,屬於稀疏矩陣,當然也沒那麼絕對噢。如圖19所示。


圖19 稀疏矩陣

稀疏矩陣如何存儲呢?

爲了節省空間,只需要記錄每個非零元素的行、列和數值即可。這就是三元組存儲法。如圖20所示。


圖20 稀疏矩陣三元組存儲

廣義表:

廣義表是線性表的推廣,也稱爲列表。它是n(n³0)個表元素組成的有限序列,記作LS= (a0, a1, a2, …,an-1)LS是表名,ai是表元素,它可以是表 (稱爲子表),可以是數據元素(稱爲原子)n爲表的長度。n=0的廣義表爲空表。

廣義表最常見就是求表頭、表尾。

表頭GetHead(L):非空廣義表的第一個元素,可以是一個單元素,也可以是一個子表。

表尾GetTail(L):非空廣義表刪除表頭元素後餘下元素所構成的表。表尾一定是一個表。

例如D=(a,(b),(a,(b,c,d))),表長爲,表頭爲a,表尾爲( (b),(a,(b,c,d)))。如圖21所示。


圖21 廣義表

發佈了53 篇原創文章 · 獲贊 185 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章