数据结构05数组和广义表
第五章 數(shù)組 和 廣義表
數(shù)組和廣義表可以看成是線性表在下述含義上的擴(kuò)展:表中的數(shù)據(jù)元素本身也是一個(gè)數(shù)據(jù)結(jié)構(gòu)。
?
5.1 數(shù)組的定義
n維數(shù)組中每個(gè)元素都受著n個(gè)關(guān)系的約束,每個(gè)元素都有一個(gè)直接后繼元素。
可以把二維數(shù)組看成是這樣一個(gè)定長線性表:它的每個(gè)數(shù)據(jù)元素也是一個(gè)定長線性表。
數(shù)組一旦定義,它的維數(shù)和維界就不再改變。因此,除了結(jié)構(gòu)的初始化和銷毀之外,數(shù)組只能有存取元素和修改元素值的操作。
?
5.2 數(shù)組的順序表示和實(shí)現(xiàn)
次序約定:
1、列序?yàn)橹餍?column major order ?FORTRAN
2、行序?yàn)橹餍?row major order ????C
?
假設(shè)每個(gè)數(shù)據(jù)元素占L個(gè)存儲(chǔ)單元,則二維數(shù)組A中的任一元素aij的存儲(chǔ)位置可由下式確定:
LOC(i,j) = LOC(0,0) + (b2?* i + j)*L
LOC(i,j)是存儲(chǔ)位置 ?LOC(0,0)稱為基地址或基址
?
n維數(shù)組定位公式
Array[b1][b2]...[bn]
LOC(j1,j2,...,jn) = LOC(0,0,...,0) + (jn?+jn-1*bn+jn-2*bn-1*bn?+ ... +j2*b3*...*bn?+j1*b2*...*bn)*L
?
數(shù)組元素的存儲(chǔ)位置是其下標(biāo)的線性函數(shù)。
由于計(jì)算各個(gè)元素存儲(chǔ)位置的時(shí)間相等,所以存取數(shù)組中任一元素的時(shí)間也相等,稱具有這一特點(diǎn)的存儲(chǔ)結(jié)構(gòu)為隨機(jī)存儲(chǔ)結(jié)構(gòu)。
? ??
5.3 矩陣的壓縮
如何存儲(chǔ)矩陣的元,使矩陣的各種運(yùn)算能有效的進(jìn)行。
二維數(shù)組可以存儲(chǔ)矩陣的元。
有的程序設(shè)計(jì)語言中還提供了各種矩陣運(yùn)算。
?
壓縮存儲(chǔ):為多個(gè)值相同的元只分配一個(gè)存儲(chǔ)空間;對(duì)零元不分配空間。
應(yīng)用壓縮的兩種情況:
1、特殊矩陣:值相同的元素或者零元素在矩陣中的分布有一定規(guī)律;
2、稀疏矩陣。
?
對(duì)稱矩陣:aij= aji ?1 <= i,j <= n 稱為n階對(duì)稱矩陣
可以為每一對(duì)對(duì)稱元分配一個(gè)存儲(chǔ)空間,即將n2個(gè)元壓縮存儲(chǔ)到n(n+1)/2個(gè)元空間中
以行序?yàn)橹餍?#xff0c;存儲(chǔ)其下三角。
以一維數(shù)組sa[n(n+1)/2]作為n階對(duì)稱矩陣A的存儲(chǔ)結(jié)構(gòu),則sa[k]和矩陣元aij之間存在一一對(duì)應(yīng)的關(guān)系:
K =?
i(i - 1)/2 - 1 + j ?當(dāng)i>=j
j(j - 1)/2 - 1 + i ?當(dāng)i < j ?//下標(biāo)誰大誰除2,一維大是下三角內(nèi)容,二維大是上三角內(nèi)容
以上存法同樣適用于三角矩陣。
?
三角矩陣:上/下三角中的元均為常數(shù)c或0的n階矩陣(不含對(duì)角線)。
除了和對(duì)稱矩陣一樣,只存儲(chǔ)其上/下三角中的元之外,再加一個(gè)存儲(chǔ)常數(shù)c的存儲(chǔ)空間即可。
對(duì)角矩陣:所有非零元集中在以主對(duì)角線為中心的帶狀區(qū)域中。即除了主對(duì)角線上和直接在對(duì)角線上、下方若干條對(duì)角線上的元之外,所有其他的元皆為零。
?
以上特殊矩陣,非零元的分布都有一個(gè)明顯的規(guī)律,從而可以將其壓縮存儲(chǔ)到一維數(shù)組中,并找到每個(gè)非零元在一維數(shù)組中的對(duì)應(yīng)關(guān)系。
?
稀疏矩陣:非零元較零元少,而且分布沒有一定規(guī)律。
稀疏因子:矩陣中非零元個(gè)數(shù)與全部個(gè)數(shù)之比。
通常認(rèn)為稀疏因子小于等于0.05時(shí)稱為稀疏矩陣。
按照壓縮存儲(chǔ)的概念,只存儲(chǔ)稀疏矩陣的非零元。
稀疏矩陣可由表示非零元的三元組?及其行列數(shù)唯一確定。
?
三種數(shù)據(jù)結(jié)構(gòu):三元組順序表、行邏輯鏈接的順序表、十字鏈表
1、三元組順序表:以行序?yàn)橹餍蝽樞蚺帕小?/p>
轉(zhuǎn)置算法:
1、將矩陣的行列值相互交換;
2、將每個(gè)三元組中的i和j相互調(diào)換;
3、重排三元組之間的次序;
方法一:找到原矩陣的列序來進(jìn)行轉(zhuǎn)置。為了找到M的每一列中所有的非零元素,需要對(duì)其三元組表從第一行起整個(gè)掃描一遍。O(列數(shù)*非零元數(shù))
方法二:先求出原矩陣每一列中非零元的個(gè)數(shù),進(jìn)而求得每一列第一個(gè)非零元在轉(zhuǎn)置矩陣中應(yīng)有的位置。 O(列數(shù)+ 非零元數(shù))
三元組順序表,又稱為有序的雙下標(biāo)法。
特點(diǎn):非零元在表中按行序有序存儲(chǔ),便于進(jìn)行依行順序處理的矩陣運(yùn)算。
若需按行號(hào)存取某一行的非零元,則需從頭開始進(jìn)行查找。
2、行邏輯鏈接的順序表:
在三元組順序表的基礎(chǔ)上,加入指示各行第一個(gè)非零元的順序表。
3、十字鏈表:
可以按任意順序輸入非零元素。
鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu),每個(gè)非零元用一個(gè)含5個(gè)域的結(jié)點(diǎn)表示,其中i、j、e分別表示該非零元所在的行、列和非零元的值,向右域right鏈接同一行中下一個(gè)非零元,向下域down鏈接同一列中下一個(gè)非零元。
同一行的非零元通過right域鏈接成一個(gè)線性鏈表,
同一列的非零元通過down域鏈接成一個(gè)線性鏈表,
每個(gè)非零元即是某個(gè)行鏈表中的一個(gè)結(jié)點(diǎn),又是某個(gè)列鏈表中的一個(gè)結(jié)點(diǎn)整個(gè)矩陣構(gòu)成一個(gè)十字交叉的鏈表。
用兩個(gè)分別存儲(chǔ)行鏈表的頭指針和列鏈表的頭指針的一維數(shù)組表示十字鏈表。
?
矩陣加法:4種情況:
(1)aij+?bij?
(2)aij??插入元素
(3)bij???插入元素
(4)aij+?bij = 0 刪除元素
?
從一個(gè)結(jié)點(diǎn)看,進(jìn)行比較、修改指針?biāo)璧臅r(shí)間是一個(gè)常數(shù);
整個(gè)運(yùn)算過程是對(duì)A和B的十字鏈表逐行掃描,其循環(huán)次數(shù)主要取決于A和B矩陣中非零元素的個(gè)數(shù)ta和tb,由此算法時(shí)間復(fù)雜度為O(ta + tb)。
?
5.4廣義表
廣義表是線性表的推廣,列表 lists
廣泛地用于人工智能等領(lǐng)域的表處理語言LISP語言,把廣義表作為基本的數(shù)據(jù)結(jié)構(gòu),就連程序也表示為一系列的廣義表。
廣義表一般記作
LS = (a1,a2,...,an?)
LS是廣義表的名稱,n是它的長度。
廣義表中的元素可以是單個(gè)元素,也可以是廣義表,分別稱為廣義表的原子和子表。
廣義表的定義是一個(gè)遞歸的定義。
當(dāng)廣義表非空時(shí),稱第一個(gè)元素為LS的表頭(Head),其余元素組成的表是LS的表尾(Tail)。
任何非空列表其表頭可能是原子,也可能是列表,但其表尾必定為列表。
?
5.5 廣義表的存儲(chǔ)結(jié)構(gòu)
由于廣義表的數(shù)據(jù)元素可以是原子,也可以是列表,因此難以用順序存儲(chǔ)結(jié)構(gòu)表示,通常采用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu),每個(gè)數(shù)據(jù)元素可用一個(gè)結(jié)點(diǎn)表示。
?
需要兩種結(jié)構(gòu)的結(jié)點(diǎn):
一種是表結(jié)點(diǎn),用以表示列表;
標(biāo)志域 + 表頭指針域 + 表尾指針域
一種是原子結(jié)點(diǎn),用以表示結(jié)點(diǎn)。
標(biāo)志域 + 值域
兩種方式:
?
enum ElemTag {ATOM,LIST}; typedef struct GLNode {elemTag tag;union{AtomType atom;struct{GLNode *hp, *tp;}ptr;}; }*GList;?
?
enum ElemTag {ATOM,LIST}; typedef struct GLNode1 {elemTag tag;union{AtomType atom;GLNode1 *hp;};GLNode1 *tp; }*GList;?
?
?
第一種結(jié)構(gòu):一個(gè)列表由表頭和表尾組成,表頭是一個(gè)表,表尾是另一個(gè)表。
第一種結(jié)構(gòu)不直觀,建議采用第二種結(jié)構(gòu)!
第二種結(jié)構(gòu):一個(gè)列表由表頭和表尾組成,表頭是原子或列表,表尾是原子或列表。
?
5.7 廣義表的遞歸算法
在對(duì)問題進(jìn)行分解、求解過程中得到的是和原問題性質(zhì)相同的子問題。
分治法(Divide and Conquer)進(jìn)行遞歸算法的設(shè)計(jì)。
遞歸定義由基本項(xiàng)和歸納項(xiàng)兩部分組成。
基本項(xiàng):描述一個(gè)或幾個(gè)遞歸過程的終結(jié)狀態(tài)。
歸納項(xiàng):描述了如何實(shí)現(xiàn)從當(dāng)前狀態(tài)到終結(jié)狀態(tài)的變化。
?
在設(shè)計(jì)遞歸函數(shù)時(shí)
(1)首先應(yīng)書寫函數(shù)的首部和規(guī)格說明,嚴(yán)格定義函數(shù)的功能和接口;
(2)對(duì)函數(shù)中的每一個(gè)遞歸調(diào)用都看成是一個(gè)簡單的操作,只要接口一致,必能實(shí)現(xiàn)規(guī)格說明中定義的功能,切忌想的太深太遠(yuǎn)。
?
?
總結(jié)
以上是生活随笔為你收集整理的数据结构05数组和广义表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据结构04串
- 下一篇: 数据结构06树和二叉树