データ構造の学習ノート - 多次元配列、行列

1. 多次元配列

(1) 配列の定義

配列は、n (n≥1)相同数据类型 データ要素で構成される制限されたシーケンスです。配列を定義するとき、固定サイズのメモリ スペースが配列に割り当てられます。要素を定義した後に配列の次元を変更することはできません。

配列の次元と次元の境界が決定されると、要素の数は固定されるため、挿入や削除の操作は実行できません。配列に対する最も一般的な 2 つの操作は、検索と変更です。

(2) 2次元配列

配列は、1 次元配列と多次元配列 (2 次元配列が一般的) に分類できます。2 次元配列は、1 次元配列の 1 次元配列とみなすことができます。シーケンス テーブルは 1 次元配列であるため、スタック、キュー、文字列と同じ論理構造である 线性结构 多次元配列は典型的な非線形構造です、入れ子になった線形構造とも言えます。

たとえば、2 次元配列 A[3][4] はメモリ内では実際には長さ 3 の 1 次元配列であり、各要素は長さ 4 の 1 次元配列であり、3 行 4 列に対応します。次のように、上から下、左から右の順に格納されます。

0 1 2 3
0 [0,0] [0,1] [0,2] [0、3]
1 [1,0] [1,1] [1,2] [1、3]
2 [2,0] [2,1] [2,2] [2、3]

配列は添字0から始まるので、m行n列の2次元配列では、最初の要素は[0, 0]、最後の要素は[m-1, n-1]となります。 4 行 4 列の 2 次元配列 A[3][4] の要素は [2, 3] です。

(3) 多次元配列の格納

2 次元配列の保存方法は 1 次元配列の保存方法と異なり、 行优先存储列优先存储

たとえば、次のように連続メモリ空間に 2 次元配列 A[3][3] を定義します。
ここに画像の説明を挿入します

A[2][0] を例として行優先順位で格納する場合、A[2][0] を格納する前に次のように格納されます。
ここに画像の説明を挿入します
列の順序 優先ストレージ。例として A[1][1] を取り上げます。A[1][1] を格納する前に、次のように格納されます。
ここに画像の説明を挿入します

(4) 多次元配列の添字の計算関連

行の添字と列の添字の範囲がそれぞれ [0, a] と [0, b] である 2 次元配列 A[i][j] を想定します。各配列要素がメモリ内の L 個の記憶ユニットを占有する場合、And配列の最初の要素の格納場所は LOC[c1][c2] です。 2 次元配列内の任意の要素 A[i][j] の格納場所を見つけますか?

1. 最初に行を保存する
[所求行乘列界限加1,然后加所求列确定位置]
(1) まず行数を決定します。次に、上記の数値に記憶単位を乗算し、最後に最初の要素の記憶場所を加算して次の結果を取得します。 LOC[i][j]=LOC[c1][c2]+[(i-c1)× (b-c2 +1)+(j-c2)]×L。
(2) プログラミング言語では、配列要素の添字は 0 から始まるため、式は次のように書き換えられます。 LOC[i][j]=LOC[0][0] +[ i×(b+1)+j]×L。

たとえば、2 次元配列 A[m][n] は行優先モードで格納され、各要素は L 個の記憶ユニットを占有します。要素 A[0][0] の格納アドレスは b. 要素 A[i][j] の格納アドレス (0 ≤ i ≤ m-1, 0 ≤ j ≤ n-1) を求めます。

分析: 2 次元配列の行要素と列要素はすべて 0 から始まるため、LOC[i][j]=b+[i×(n-1+1)+j]× L=b+[i×n+j]×L。
2. カラムファーストストレージ
[所求列乘行界限加1,然后加所求行确定位置]
(1) まず確認してください列が何個あるか、行数を加算し、次に記憶単位を乗算し、最後に最初の要素の記憶場所を加算すると、次のようになります。 LOC[i][j]=LOC[c1][c2]+[ (j-c1)×(a-c2+1)+(j-c1)]×L。
(2) プログラミング言語では、配列要素の添え字は 0 から始まるため、式は次のように書き換えられます。 LOC[i][j]=LOC[0][0] +[ j×(a+1)+i]×L。

たとえば、7 行と 6 列の配列 a が列優先で格納され、ベース アドレスが 1024 で、各要素が 2 つのストレージ ユニットを占有するとします。行 0 と列 0 がない場合は、次の値を見つけます。行 4 と列 5。要素の記憶アドレス。

分析: 最初の要素は a[1][1] であるため、それを減算して計算に代入する必要があります。つまり、
LOC[4][5] ]=1024+[(5-1)×(7-1+1)+(4-1)]×2=1024+62=1086。

  • 配列 An×n (正方行列) の場合、その要素 aij行優先と列優先で格納する場合のアドレスの差は、(n-1)(i-j) になります。

2. マトリックス

(1) 特殊行列と疎行列

行列内に同じ要素またはゼロ要素が 一定のパターンで分布している行列を 特殊矩阵 と呼び、その逆を 稀疏矩阵。簡単に言うと、特殊な行列は特殊であるため、その中に同一またはゼロの要素が多数存在し、行列内に一定の法則が分布していることを意味します。

一般的な特殊行列には、対称行列、非対称行列、上三角行列、下三角行列、対角行列などが含まれます。たとえば、対角行列では、対角線上の要素のみが存在し、残りの要素はゼロになります。
ここに画像の説明を挿入します

(2) 対称行列とその圧縮記憶

n 次正方行列が Ai×j=Aj×i< を満たす場合/ a> 圧縮して保存すると、要素が 1 つの形式で保存されます。行順の次元配列 実装するには、まず配列サイズを決定します 行列は次数 n=4 の 4×4 正方行列なので、必要な 1 次元配列サイズは n(1+n)/2 となります=(4×5)/2=10 、対称行列であるため、上三角部分または下三角部分の要素のみが保存されます。ここでは、例として上三角要素の保存を取り上げます。
たとえば、行列 B は次のとおりです。これを対称行列とみなしてください。 を対称行列と呼びます。対称行列の上三角部分と下三角部分の要素は同じに対応するため、対称行列を保存する際にスペースの無駄を避けるために、上三角部分または下三角部分の要素のみを保存して保存することができます。 1 次元配列のサイズは 1+2+…+n=n(1+n)/2 です。
ここに画像の説明を挿入します

ここに画像の説明を挿入します

(3) 対角行列

三重対角行列とは、主対角線を中心とした3つの対角領域に非ゼロ要素が集中し、その他の領域がゼロである対角行列です。

(4) スパース行列の圧縮保存

前述したように、スパース行列の非ゼロ要素の分布は特殊行列の分布とは逆であり、不規則です。スパース行列の要素のほとんどは 0 であり、非ゼロ要素の分布と同様に、それらも不規則です。マトリックス圧縮の目的は、ストレージ領域を節約することです。
1. トリプレット テーブル
スパース行列を圧縮して保存するには、行列内の非ゼロ要素の値を保存するだけでなく、要素が配置されている行と列はトリプレット テーブル (行、列、値) を形成するため、記憶領域が削減されます。スパース行列の非ゼロ要素と、それに対応する行番号と列番号は、トリプルの形式で配列に格納されるため、そのように圧縮して格納した後、配列の添え字を介して行列の要素に直接アクセスすることは不可能です。 、ランダムアクセス特性が失われます。さらに、スパース行列のトリプル テーブルは、クロスリンク リスト方式を使用して保存することもできます。 [スパース行列の 2 つの記憶構造は、トリプル テーブル (配列) とクロスリンク リストです]

//以整型int为例,可替换其他类型
typedef struct{
    
    
	int i,j;	//行与列
	int x;		//值
}Sparsematrix;

たとえば、スパース行列 A は圧縮されて保存されます。
ここに画像の説明を挿入します
対応するトリプル テーブルは次のとおりです。

i(行) j (列) x (値)
1 1 4
1 3 2
2 0 5

たとえば、10 個の非ゼロ要素を含む 100×90 の疎行列があります。各整数が 2 バイトを占めると仮定します。行列を表すのにトリプルを使用する場合は、必要なバイト数を見つけます。

分析: トリプル テーブルには行、列、および値が含まれます。各整数は 2 バイトを占有するため、10 個の非ゼロ要素は 3×2×10=60 バイトを占有します。さらに、トリプル内の行と列の数もあります。非ゼロ要素の数と合計数は 6 バイト、合計 60+6=66 バイトです。

2. 相互リンク リスト
相互リンク リスト法では、疎行列の行と列は、5 つの成分に対応する先頭ノードを持つリンク リストで表されます。 : 行、列、データ フィールド、下位ノードを指すポインタと右ノードを指すポインタ、ノードの構造は次のとおりです。
ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/qq_43085848/article/details/134536961