稀疏矩陣的儲存方法(3種)及C語言程式碼實現
阿新 • • 發佈:2018-12-17
稀疏矩陣,即含有少量非 0 元素的矩陣,如圖 1 所示:
圖 1 稀疏矩陣
該矩陣中非 0 元素的數量比較少,與其使用普通方式將矩陣中的所有資料元素一一儲存,不如只儲存非 0 元素更節省記憶體空間,拿圖 1 中矩陣來說,只需儲存元素 3、4、5 即可(此類儲存方式被稱為稀疏矩陣的壓縮儲存)。
稀疏矩陣(壓縮)儲存的方式有 3 種,分別為:三元組順序表、行邏輯連結的順序表和十字連結串列。
三元組順序表
儲存稀疏矩陣,需記錄矩陣中每個非 0 元素的 3 個要素:非 0 元素的值、所在行標(用 i 表示)以及所在列標(用 j 表示),每個非 0 元素的 3 要素都可以用一個三元組(行標、列標、元素值)來表示,矩陣中所有非 0 元素的三元組可以通過順序表來儲存。此方法也被稱為稀疏矩陣的三元組表示法因此,每個非 0 元素的三元組需要使用結構體進行自定義:
//三元組結構體 typedef struct { int i,j;//行標i,列標j int data;//元素值 }triple;稀疏矩陣的儲存,一方面要儲存矩陣中所有非 0 元素的三元組,同時還要記錄該稀疏矩陣的行數、列數以及矩陣中非 0 元素的個數,因此表示矩陣的結構也需要使用結構體實現:
#define number 100 //矩陣的結構表示 typedef struct { triple data[number];//儲存該矩陣中所有非0元素的三元組 int n,m,num;//n和m分別記錄矩陣的行數和列數,num記錄矩陣中所有的非0元素的個數 }TSMatrix;
行邏輯連結的順序表
使用三元組順序表儲存的稀疏矩陣,當需要提取矩陣某一行的非 0 元素時,只能遍歷整個順序表,效率很低。為了提高查詢的效率,可在三元組順序表的基礎上,增加一個數組用於記錄每一行第一個非 0 元素的儲存位置,這樣的儲存結構被稱為:行邏輯連結的順序表。
結構程式碼:
#define number 100 typedef struct { int i,j; int data; }triple; typedef struct { triple data[number]; int rpos[number];//儲存各行第一個非0元素在三元組表中的位置 int n,m,num; }TSMatrix;
十字連結串列
以上兩種儲存稀疏矩陣的方法,說到底,還是運算元組,在進行矩陣運算過程中,如果有插入非 0 元素或者刪除某一個元素的操作,可能需要大量的移動陣列中的三元組。這時,就要考慮使用連結串列的儲存結構。例如在進行“將矩陣 B 加到矩陣 A 上”的操作時,矩陣 A 中的資料元素會發生很大的變化,之前的 0 元素可能變成非 0 元素,非 0 元素也可能變成 0 (正負數相加為 0)。在這種情況下,就需要使用連結串列的儲存結構來儲存矩陣,這種儲存方式稱為:十字連結串列法。
例如,將下列矩陣以十字連結串列的方式儲存起來:
圖4 十字連結串列 採用十字連結串列法儲存矩陣的非 0 元素時,連結串列中的結點由 5 部分組成:
圖5 十字連結串列中的結點 兩個指標域:一個指向所在列的下一個元素,一個指向所在行的下一個元素。
結構程式碼:
typedef struct OLNode{ int i,j; int data; struct OLNode * right,*down; }OLNode; //此結構體表示一個矩陣,其中包含矩陣的行數,列數,非0元素的個數以及用於儲存各行以及各列元素頭指標的動態陣列rhead和chead。 typedef struct { OLNode * rhead,*chead; int n,m,num; }CrossList;
總結
稀疏矩陣的三種不同的儲存方法,採用哪種方法要看程式具體要實現的功能:- 如果想完成例如矩陣的轉置這樣的操作,宜採用三元組順序表;
- 如果想實現矩陣的乘法這樣的功能,宜採用行邏輯連結的順序表;
- 如果矩陣運算過程中(例如矩陣的加法),需要不斷地插入非 0 元素或刪除變為 0 的元素,宜採用十字連結串列法。
有關三種儲存方法的例項:矩陣轉置、矩陣的乘法和矩陣的加法各自利用一節來詳細介紹。