數(shù)組
從本質(zhì)上講,數(shù)組與順序表、鏈表、棧和隊(duì)列一樣,都用來存儲具有 "一對一" 邏輯關(guān)系數(shù)據(jù)的線性存儲結(jié)構(gòu)。只因各編程語言都默認(rèn)將數(shù)組作為基本數(shù)據(jù)類型,使初學(xué)者對數(shù)組有了 "只是基本數(shù)據(jù)類型,不是存儲結(jié)構(gòu)" 的誤解。
數(shù)組結(jié)構(gòu)的實(shí)現(xiàn)使用的是順序存儲結(jié)構(gòu)。
根據(jù)數(shù)組中存儲數(shù)據(jù)之間邏輯結(jié)構(gòu)的不同,數(shù)組可細(xì)分為一維數(shù)組、二維數(shù)組、...、n 維數(shù)組:
- 一維數(shù)組,指的是存儲不可再分?jǐn)?shù)據(jù)元素的數(shù)組,如圖 1 所示:

-
二維數(shù)組,指的存儲一維數(shù)組的一維數(shù)組,如圖 2 所示:
圖2:二維數(shù)組示意圖 n維數(shù)組,指的是存儲n-1維數(shù)組的一維數(shù)組
注意:無論數(shù)組的維數(shù)是多少,數(shù)組中的數(shù)據(jù)類型都必須一致。
矩陣(稀疏矩陣)壓縮存儲(3種方式)
數(shù)據(jù)結(jié)構(gòu)中提供針對某些特殊矩陣的壓縮存儲結(jié)構(gòu),這里所說的特殊矩陣,主要分為以下兩類:
- 1.含有大量相同元素的矩陣,比如對稱矩陣
- 2.含有大量0元素的矩陣,比如稀疏矩陣、上(下)三角矩陣
針對以上兩類矩陣,數(shù)據(jù)結(jié)構(gòu)的壓縮存儲思想是:矩陣中的相同數(shù)據(jù)元素(包括元素 0)只存儲一個(gè)。
對稱矩陣
數(shù)據(jù)元素沿主對角線對應(yīng)相等,這類矩陣稱為對稱矩陣。

矩陣中有兩條對角線,其中圖 1 中的對角線稱為主對角線,另一條從左下角到右上角的對角線為副對角線。對稱矩陣指的是各數(shù)據(jù)元素沿主對角線對稱的矩陣。
我們可以使用一維數(shù)組存儲對稱矩陣。由于矩陣中沿對角線兩側(cè)的數(shù)據(jù)相等,因此數(shù)組中只需存儲對角線一側(cè)(包含對角線)的數(shù)據(jù)即可。
對稱矩陣的實(shí)現(xiàn)過程是,若存儲下三角中的元素,只需將各元素所在的行標(biāo) i 和列標(biāo) j 代入下面的公式:

存儲上三角的元素要將各元素的行標(biāo) i 和列標(biāo) j 代入另一個(gè)公式:

最終求得的 k 值即為該元素存儲到數(shù)組中的位置(矩陣中元素的行標(biāo)和列標(biāo)都從 1 開始)。
例如,在數(shù)組 skr[6] 中存儲圖 1 中的對稱矩陣,則矩陣的壓縮存儲狀態(tài)如圖 6 所示(存儲上三角和下三角的結(jié)果相同):

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

結(jié)合圖 6,數(shù)組下標(biāo)為 3 的位置存儲的是元素 3,與圖 3 對應(yīng)。
上(下)三角矩陣

主對角線下的數(shù)據(jù)元素全部為0的矩陣為上三角矩陣(圖 4a)),主對角線上元素全部為0的矩陣為下三角矩陣(圖 4b))。上(下)三角矩陣存儲元素和提取元素的過程和對稱矩陣相同。
稀疏矩陣

壓縮存儲稀疏矩陣的方法是:只存儲矩陣中的非 0 元素,與前面的存儲方法不同,稀疏矩陣非 0 元素的存儲需同時(shí)存儲該元素所在矩陣中的行標(biāo)和列標(biāo)。
例如,存儲圖 9 中的稀疏矩陣,需存儲以下信息:
- (1,1,1):數(shù)據(jù)元素為 1,在矩陣中的位置為 (1,1);
- (3,3,1):數(shù)據(jù)元素為 3,在矩陣中的位置為 (3,1);
- (5,2,3):數(shù)據(jù)元素為 5,在矩陣中的位置為 (2,3);
- 除此之外,還要存儲矩陣的行數(shù) 3 和列數(shù) 3;
由此,可以成功存儲一個(gè)稀疏矩陣。
矩陣壓縮存儲的3種方式
對于以上 3 種特殊的矩陣,對稱矩陣和上下三角矩陣的實(shí)現(xiàn)方法是相同的,且實(shí)現(xiàn)過程比較容易,僅需套用上面給出的公式即可。
稀疏矩陣的壓縮存儲,數(shù)據(jù)結(jié)構(gòu)提供有3種具體實(shí)現(xiàn)方式:
- 1.三元組順序表
- 2.行邏輯鏈接的順序表
- 3.十字鏈表
三元組順序表
圖 9 是一個(gè)稀疏矩陣,若對其進(jìn)行壓縮存儲,矩陣中各非 0 元素的存儲狀態(tài)如圖 10 所示:

圖10存儲的是三元組(即由 3 部分?jǐn)?shù)據(jù)組成的集合),組中數(shù)據(jù)分別表示(行標(biāo),列標(biāo),元素值)。
public class Triple {
int i; //行標(biāo)i
int j; //列標(biāo)j
int data; //元素值
}
public class TSMatrix{
int n; // 矩陣行數(shù)
int m; // 矩陣列數(shù)
int num; // 矩陣有效數(shù)據(jù)數(shù)量
Triple[] triple = new Triple[num];//矩陣3元組元素
}
行邏輯鏈接順序表
三元組順序表每次提取指定元素都需要遍歷整個(gè)數(shù)組,運(yùn)行效率很低。
行邏輯鏈接的順序表。它可以看作是三元組順序表的升級版,即在三元組順序表的基礎(chǔ)上改善了提取數(shù)據(jù)的效率。

圖 11 是一個(gè)稀疏矩陣,當(dāng)使用行邏輯鏈接的順序表對其進(jìn)行壓縮存儲時(shí),需要做以下兩個(gè)工作:
-
將矩陣中的非 0 元素采用三元組的形式存儲到一維數(shù)組 data 中,如圖 2 所示(和三元組順序表一樣):
圖12:三元組存儲稀疏矩陣
使用數(shù)組 rpos 記錄矩陣中每行第一個(gè)非 0 元素在一維數(shù)組中的存儲位置。如圖 13 所示:

通過以上兩步操作,即實(shí)現(xiàn)了使用行邏輯鏈接的順序表存儲稀疏矩陣。
此時(shí),如果想從行邏輯鏈接的順序表中提取元素,則可以借助 rpos 數(shù)組提高遍歷數(shù)組的效率。
例如,提取圖 11 稀疏矩陣中的元素 2 的過程如下:
- 由 rpos 數(shù)組可知,第一行首個(gè)非 0 元素位于data[1],因此在遍歷此行時(shí),可以直接從第 data[1] 的位置開始,一直遍歷到下一行首個(gè)非 0 元素所在的位置(data[3])之前
十字鏈表法
對于壓縮存儲稀疏矩陣,無論是使用三元組順序表還是使用行邏輯鏈接的順序表,歸根結(jié)底是使用數(shù)組存儲稀疏矩陣。介于數(shù)組 "不利于插入和刪除數(shù)據(jù)" 的特點(diǎn),以上兩種壓縮存儲方式都不適合解決類似 "向矩陣中添加或刪除非 0 元素" 的問題。
十字鏈表法存儲稀疏矩陣,該存儲方式采用的是 "鏈表+數(shù)組" 結(jié)構(gòu),如圖14所示:

可以看到,使用十字鏈表壓縮存儲稀疏矩陣時(shí),矩陣中的各行各列都各用一各鏈表存儲,與此同時(shí),所有行鏈表的表頭存儲到一個(gè)數(shù)組(rhead),所有列鏈表的表頭存儲到另一個(gè)數(shù)組(chead)中。
因此,各個(gè)鏈表中節(jié)點(diǎn)的結(jié)構(gòu)應(yīng)如圖15 所示:

兩個(gè)指針域分別用于鏈接所在行的下一個(gè)元素以及所在列的下一個(gè)元素。
矩陣(稀疏矩陣)的轉(zhuǎn)置算法
矩陣的轉(zhuǎn)置,即互換矩陣中所有元素的行標(biāo)和列標(biāo),如圖16所示:

但如果想通過程序?qū)崿F(xiàn)矩陣的轉(zhuǎn)置,互換行標(biāo)和列標(biāo)只是第一步。因?yàn)閷?shí)現(xiàn)矩陣轉(zhuǎn)置的前提是將矩陣存儲起來,數(shù)據(jù)結(jié)構(gòu)中提供了 3 種存儲矩陣的結(jié)構(gòu),分別是三元組順序表、行邏輯鏈接的順序表、十字鏈表。如果采用前兩種結(jié)構(gòu),矩陣的轉(zhuǎn)置過程會涉及三元組表也跟著改變的問題,如圖 2 所示:

圖 2a) 表示的是圖 1 中轉(zhuǎn)置之前矩陣的三元組表,2b) 表示的是圖 1 中矩陣轉(zhuǎn)置后對應(yīng)的三元組表。由此發(fā)現(xiàn),三元組順序表中數(shù)組的位置發(fā)生了變化。
不僅如此,如果矩陣的行數(shù)和列數(shù)不等,也需要將它們互換。
因此通過以上分析,矩陣轉(zhuǎn)置的實(shí)現(xiàn)過程需完成以下 3 步:
- 1.將矩陣的行數(shù)和列數(shù)互換
- 2.將三元組表(存儲矩陣)中的 i 列和 j 列互換,實(shí)現(xiàn)矩陣的轉(zhuǎn)置
- 3.以 j 為序列,重新排列三元組表中存儲各三元組的先后順序
此 3 步中,前兩步比較簡單,關(guān)鍵在于最后一步的實(shí)現(xiàn)。
矩陣轉(zhuǎn)置的實(shí)現(xiàn)思路是:不斷遍歷存儲矩陣的三元組表,每次都取出表中 j 列最小的那一個(gè)三元組,互換行標(biāo)和列標(biāo)的值,并按次序存儲到一個(gè)新三元組表中。
例如,將圖 2a) 三元組表存儲的矩陣進(jìn)行轉(zhuǎn)置的過程為:
1.新建一個(gè)三元組表(用于存儲轉(zhuǎn)置矩陣),并將原矩陣的行數(shù)和列數(shù)互換賦值給新三元組;
-
2.遍歷三元組表,找到表中 j 列最小值 1 所在的三元組 (3,1,6),然后將其行標(biāo)和列標(biāo)互換后添加到一個(gè)新的三元組表中,如圖 18 所示:
圖18:矩陣轉(zhuǎn)置的第一個(gè)過程 -
3.繼續(xù)遍歷三元組表,找到表中 j 列次小值為 2 的三元組,分別為 (1,2,1)、(2,2,3) 和 (3,2,5),根據(jù)找到它們的先后次序?qū)⒏髯缘男袠?biāo)和列標(biāo)互換后添加到新三元組表中,如圖 19 所示:
圖19:矩陣轉(zhuǎn)置的第二個(gè)過程
對比圖 19 和圖 2b) 可以看到,矩陣被成功地轉(zhuǎn)置。
由于此算法中需要嵌套使用了兩個(gè) for 循環(huán),時(shí)間復(fù)雜度為 O(n2)。
稀疏矩陣的快速轉(zhuǎn)置算法
稀疏矩陣快速轉(zhuǎn)置算法和普通算法的區(qū)別僅在于第 3 步,快速轉(zhuǎn)置能夠做到遍歷一次三元組表即可完成第 3 步的工作。
稀疏矩陣的快速轉(zhuǎn)置是這樣的,在普通算法的基礎(chǔ)上增設(shè)兩個(gè)數(shù)組(假
設(shè)分別為 array 和 copt):
- array 數(shù)組負(fù)責(zé)記錄原矩陣每一列非 0 元素的個(gè)數(shù)。以圖 1 為例,則對應(yīng)的 array 數(shù)組如圖 20 所示:
圖20:每一列非0元素的個(gè)數(shù)
圖 2 中 array 數(shù)組表示,原稀疏矩陣中第一列有 1 個(gè)非 0 元素,第二列有 2 個(gè)非 0 元素。 -
copt 數(shù)組用于計(jì)算稀疏矩陣中每列第一個(gè)非 0 元素在新三元組表中存放的位置。
我們通常默認(rèn)第一列首個(gè)非 0 元素存放到新三元組表中的位置為 1,然后通過 cpot[col] = cpot[col-1] + array[col-1] 公式可計(jì)算出后續(xù)各列首個(gè)非 0 元素存放到新三元組表的位置。拿圖 1 中的稀疏矩陣來說,它對應(yīng)的 copt 數(shù)組如圖 21 所示:
圖21:copt數(shù)組示意圖
圖 21 中的 copt 數(shù)組表示,原稀疏矩陣中第 2 列首個(gè)非 0 元素存放到新三元組表的位置為 2。
注意,cpot[col] = cpot[col-1] + array[col-1] 的意思是,后一列首個(gè)非 0 元素存放的位置等于前一列首個(gè)非 0 元素的存放位置,加上該列非 0 元素的個(gè)數(shù)。由此可以看出,copt 數(shù)組才是最終想要的,而 array 數(shù)組的設(shè)立只是為了幫助我們得到 copt 數(shù)組。
//具體代碼省略
稀疏矩陣快速轉(zhuǎn)置算法的時(shí)間復(fù)雜度為 O(n)。即使在最壞的情況下(矩陣中全部都是非 0 元素),該算法的時(shí)間復(fù)雜度也才為 O(n2)。
矩陣乘法
矩陣相乘的前提條件是:乘號前的矩陣的列數(shù)要和乘號后的矩陣的行數(shù)相等。且矩陣的乘法運(yùn)算沒有交換律,即 AB 和 BA 是不一樣的。假設(shè)下面是矩陣A:
| 3 | 0 | 0 | 5 |
|---|---|---|---|
| 0 | -1 | 0 | 0 |
| 2 | 0 | 0 | 0 |
下面是矩陣B:
| 0 | 2 |
|---|---|
| 1 | 0 |
| -2 | 4 |
| 0 | 0 |
由于矩陣 A 的列數(shù)和矩陣 B 的行數(shù)相等,可以進(jìn)行 AB 運(yùn)算(不能進(jìn)行 BA 運(yùn)算)。計(jì)算方法是:用矩陣 A 的第 i 行和矩陣 B 中的每一列 j 對應(yīng)的數(shù)值做乘法運(yùn)算,乘積一一相加,所得結(jié)果即為矩陣 C 中第 i 行第 j 列的值。
例如:C12 = 6 是因?yàn)椋篈11B12 + A12B22 + A13B32 + A14B42,即 32 + 00 + 04 + 50 = 6 ,因?yàn)檫@是 A 的第 1 行和 B的第 2 列的乘積和,所以結(jié)果放在 C 的第 1 行第 2 列的位置。
結(jié)果矩陣C為:
| 0 | 6 |
|---|---|
| -1 | 0 |
| 0 | 4 |
例如,A 是 m1n1 矩陣,B 是 m2n2 矩陣(前提必須是 n1 == m2 ):
普通算法的時(shí)間復(fù)雜度為 O(m1*n2*n1)
基于行邏輯鏈接的順序表的矩陣乘法
具體過程不描述,請自行百度,這里只說結(jié)論。
當(dāng)稀疏矩陣 Amn 和稀疏矩陣 Bnp 采用行邏輯鏈接的順序表做乘法運(yùn)算時(shí),在矩陣 A 的列數(shù)(矩陣 B 的行數(shù)) n 不是很大的情況下,算法的時(shí)間復(fù)雜度相當(dāng)于 O(m*p),比普通算法要快很多
矩陣加法
矩陣之間能夠進(jìn)行加法運(yùn)算的前提條件是:各矩陣的行數(shù)和列數(shù)必須相等。
在行數(shù)和列數(shù)都相等的情況下,矩陣相加的結(jié)果就是矩陣中對應(yīng)位置的值相加所組成的矩陣,例如:

十字鏈表法
過程有點(diǎn)復(fù)雜,具體請自行百度,這里只說結(jié)論
使用十字鏈表法解決稀疏矩陣的壓縮存儲的同時(shí),在解決矩陣相加的問題中,對于某個(gè)單獨(dú)的結(jié)點(diǎn)來說,算法的時(shí)間復(fù)雜度為一個(gè)常數(shù)(全部為選擇結(jié)構(gòu)),算法的整體的時(shí)間復(fù)雜度取決于兩矩陣中非 0 元素的個(gè)數(shù)。
廣義表
數(shù)組即可以存儲不可再分的數(shù)據(jù)元素(如數(shù)字 5、字符 'a'),也可以繼續(xù)存儲數(shù)組(即 n 維數(shù)組)。
但需要注意的是,以上兩種數(shù)據(jù)存儲形式絕不會出現(xiàn)在同一個(gè)數(shù)組中。例如,我們可以創(chuàng)建一個(gè)整形數(shù)組去存儲 {1,2,3},我們也可以創(chuàng)建一個(gè)二維整形數(shù)組去存儲 {{1,2,3},{4,5,6}},但數(shù)組不適合用來存儲類似 {1,{1,2,3}} 這樣的數(shù)據(jù)。
有人可能會說,創(chuàng)建一個(gè)二維數(shù)組來存儲{1,{1,2,3}}。在存儲上確實(shí)可以實(shí)現(xiàn),但無疑會造成存儲空間的浪費(fèi)。
對于存儲 {1,{1,2,3}} 這樣的數(shù)據(jù),更適合用廣義表結(jié)構(gòu)來存儲。
廣義表,又稱列表,也是一種線性存儲結(jié)構(gòu)。
同數(shù)組類似,廣義表中既可以存儲不可再分的元素,也可以存儲廣義表,記作:
LS = (a1,a2,…,an)
其中,LS 代表廣義表的名稱,an 表示廣義表存儲的數(shù)據(jù)。廣義表中每個(gè) ai 既可以代表單個(gè)元素,也可以代表另一個(gè)廣義表。
原子和子表
通常,廣義表中存儲的單個(gè)元素稱為 "原子",而存儲的廣義表稱為 "子表"。
以下是廣義表存儲數(shù)據(jù)的一些常用形式:
- A = ():A 表示一個(gè)廣義表,只不過表是空的。
- B = (e):廣義表 B 中只有一個(gè)原子 e。
- C = (a,(b,c,d)) :廣義表 C 中有兩個(gè)元素,原子 a 和子表 (b,c,d)。
- D = (A,B,C):廣義表 D 中存有 3 個(gè)子表,分別是A、B和C。這種表示方式等同于 D = ((),(e),(b,c,d)) 。
- E = (a,E):廣義表 E 中有兩個(gè)元素,原子 a 和它本身。這是一個(gè)遞歸廣義表,等同于:E = (a,(a,(a,…)))。
注意,A = () 和 A = (()) 是不一樣的。前者是空表,而后者是包含一個(gè)子表的廣義表,只不過這個(gè)子表是空表。
廣義表的表頭和表尾
當(dāng)廣義表不是空表時(shí),稱第一個(gè)數(shù)據(jù)(原子或子表)為"表頭",剩下的數(shù)據(jù)構(gòu)成的新廣義表為"表尾"。
強(qiáng)調(diào)一下,除非廣義表為空表,否則廣義表一定具有表頭和表尾,且廣義表的表尾一定是一個(gè)廣義表。
例如在廣義表中 LS={1,{1,2,3},5} 中,表頭為原子 1,表尾為子表 {1,2,3} 和原子 5 構(gòu)成的廣義表,即 {{1,2,3},5}。
再比如,在廣義表 LS = {1} 中,表頭為原子 1 ,但由于廣義表中無表尾元素,因此該表的表尾是一個(gè)空表,用 {} 表示。
廣義表的存儲結(jié)構(gòu)
由于廣義表中既可存儲原子(不可再分的數(shù)據(jù)元素),也可以存儲子表,因此很難使用順序存儲結(jié)構(gòu)表示,通常情況下廣義表結(jié)構(gòu)采用鏈表實(shí)現(xiàn)。
使用鏈表存儲廣義表,首先需要確定鏈表中節(jié)點(diǎn)的結(jié)構(gòu)。由于廣義表中可同時(shí)存儲原子和子表兩種形式的數(shù)據(jù),因此鏈表節(jié)點(diǎn)的結(jié)構(gòu)也有兩種,如圖23 所示:

如圖 23所示,表示原子的節(jié)點(diǎn)由兩部分構(gòu)成,分別是 tag 標(biāo)記位和原子的值,表示子表的節(jié)點(diǎn)由三部分構(gòu)成,分別是 tag 標(biāo)記位、hp 指針和 tp 指針。
tag 標(biāo)記位用于區(qū)分此節(jié)點(diǎn)是原子還是子表,通常原子的 tag 值為 0,子表的 tag 值為 1。子表節(jié)點(diǎn)中的 hp 指針用于連接本子表中存儲的原子或子表,tp 指針用于連接廣義表中下一個(gè)原子或子表。
例如,廣義表 {a,{b,c,d}} 是由一個(gè)原子 a 和子表 {b,c,d} 構(gòu)成,而子表 {b,c,d} 又是由原子 b、c 和 d 構(gòu)成,用鏈表存儲該廣義表如圖 24 所示:

另一種廣義表存儲結(jié)構(gòu)
如果你覺得圖 24 這種存儲廣義表的方式不合理,可以使用另一套表示廣義表中原子和子表結(jié)構(gòu)的節(jié)點(diǎn),如圖 25 所示:

采用圖 25 中的節(jié)點(diǎn)結(jié)構(gòu)存儲廣義表 {a,{b,c,d}} 的示意圖如圖 26 所示:

廣義表的深度和長度
廣義表的長度
由于廣義表中可以同時(shí)存儲原子和子表兩種類型的數(shù)據(jù),因此在計(jì)算廣義表的長度時(shí)規(guī)定,廣義表中存儲的每個(gè)原子算作一個(gè)數(shù)據(jù),同樣每個(gè)子表也只算作是一個(gè)數(shù)據(jù)。
前面我們用 LS={a1,a2,...,an} 來表示一個(gè)廣義表,其中每個(gè) ai 都可用來表示一個(gè)原子或子表,其實(shí)它還可以表示廣義表 LS 的長度為 n。
廣義表規(guī)定,空表 {} 的長度為 0
廣義表的存儲使用的是鏈表結(jié)構(gòu),且有以下兩種方式(如圖 1 所示):

對于圖 a) 來說,只需計(jì)算最頂層(紅色標(biāo)注)含有的節(jié)點(diǎn)數(shù)量,即可求的廣義表的長度。
對于圖 b) 來說,由于其最頂層(藍(lán)色標(biāo)注)表示的此廣義表,而第二層(紅色標(biāo)注)表示的才是該廣義表中包含的數(shù)據(jù)元素,因此可以通過計(jì)算第二層中包含的節(jié)點(diǎn)數(shù)量,即可求得廣義表的長度。
廣義表的深度
廣義表的深度,可以通過觀察該表中所包含括號的層數(shù)間接得到。

從圖 28 中可以看到,此廣義表從左往右數(shù)有兩層左括號(從右往左數(shù)也是如此),因此該廣義表的深度為 2。
編寫程序計(jì)算廣義表的深度時(shí),可以采用遞歸的方式:
1.依次遍歷廣義表 C 的每個(gè)節(jié)點(diǎn),若當(dāng)前節(jié)點(diǎn)為原子(tag 值為 0),則返回 0;若為空表,則返回 1;反之,則繼續(xù)遍歷該子表中的數(shù)據(jù)元素。
2.設(shè)置一個(gè)初始值為 0 的整形變量 max,每次遞歸過程返回時(shí),令 max 與返回值進(jìn)行比較,并取較大值。這樣,當(dāng)整個(gè)廣義表遞歸結(jié)束時(shí),max+1 就是廣義表的深度。
廣義表的復(fù)制
對于任意一個(gè)非空廣義表來說,都是由兩部分組成:表頭和表尾。反之,只要確定的一個(gè)廣義表的表頭和表尾,那么這個(gè)廣義表就可以唯一確定下來。
復(fù)制一個(gè)廣義表,也是不斷的復(fù)制表頭和表尾的過程。如果表頭或者表尾同樣是一個(gè)廣義表,依舊復(fù)制其表頭和表尾。
所以,復(fù)制廣義表的過程,其實(shí)就是不斷的遞歸,復(fù)制廣義表中表頭和表尾的過程。





