Matrix-C++

Eine Matrix, die eine zweidimensionale Darstellung einer linearen Tabelle ist. Zur Darstellung einer Matrix kann ein zweidimensionales Array verwendet werden , und einige weit verbreitete und spezielle Formen von Matrizen, wie z. B. dünn besetzte Matrizen und quasi-diagonale Matrizen, können komprimiert und gespeichert werden.

Symmetrische und dreieckige Matrizen

Eine Matrix heißt quadratisch, wenn sie die gleiche Anzahl an Zeilen und Spalten hat. Es gibt zwei spezielle Arten quadratischer Matrizen: symmetrisch und dreieckig. Da die symmetrische Matrix viele wiederholte Elemente enthält, können die nicht wiederholten Teile der symmetrischen Matrix reserviert werden, um Platz zu sparen. Diese Art von Ausdrucksmethode, die nur einen Teil der Elementinformationen der Matrix beibehält, aber die ursprüngliche Matrix wiederherstellen kann, wird als komprimierte Speicherung der Matrix bezeichnet.

Die komprimierte Speichermethode einer symmetrischen Matrix besteht darin, nur die unteren Dreieckselemente der Matrix beizubehalten. Die Kompressionsreduzierung von Dreiecksmatrizen ähnelt der von symmetrischen Matrizen.

//矩阵的类型定义
constexpr auto M = 100; //矩阵行数的上限
constexpr auto N = 100; //矩阵列数的上限
typedef int datatype;
struct matrix {
	datatype a[M][N];
	int row; //矩阵的行数
	int col; //矩阵的列数
	matrix(int r = 0, int c = 0) :row(r), col(c) {
		memset(a, 0, sizeof(a));
	}
	matrix(datatype b[M][N], int r, int c) :row(r), col(c) { //用数组b初始化当前矩阵
		for (int i = 0; i < r; i++)
			for (int j = 0; j < c; j++)
				a[i][j] = b[i][j];
	}
};

//两个矩阵相乘,mat1*mat2,相乘结果作为返回值
matrix mat(matrix mat1, matrix mat2) {
	if (mat1.col != mat2.col) {
		cout << "矩阵不能相乘!" << endl;
		return NULL;
	}
	matrix mat(mat1.row, mat2.col); //mat的行数和列数分别mat1的行数和mat2的列数
	for (int i = 0; i < mat1.row; i++) {
		for (int j = 0; j < mat1.col; j++) {
			mat.a[i][j] = 0;
			for (int k = 0; k < mat1.col; k++) {
				mat.a[i][j] += mat1.a[i][k] * mat2.a[k][j];
			}
		}
	}
	return mat;
}

//特殊矩阵的表示与操作
//对称矩阵的压缩和还原

//将对称矩阵mat压缩为一维向量,结果作为返回值
vector<int> convert(matrix mat) {
	vector<int>ret;
	for (int i = 0; i < mat.row; i++) {
		for (int j = 0; j <= i; j++) {
			ret.push_back(mat.a[i][j]);
		}
	}
	return ret;
}

//将压缩的对称矩阵ve还原成二维表示方法,结果作为返回值
matrix convert(vector<int>ve) {
	matrix mat;
	int i = 0,j = 0;
	for (int k = 0; k < ve.size(); k++) {
		j = k - i * (i + 1) / 2; //数学计算,判断列数
		mat.a[i][j] = mat.a[j][i] = ve[k];
		if (i * (i + 2) / 2 < k) i++; //判断是否进入下一行
	}
	mat.row = mat.col = i;
	return mat;
}

spärliche Matrix

Das Verhältnis der Anzahl der Nicht-Null-Elemente in der Matrix zur Gesamtzahl der Matrixelemente wird als Dichte der Matrix bezeichnet, d. h. wenn es t Nicht-Null-Elemente in einer m*n-Matrix gibt, ist die Dichte der Matrix ist y=t/(mn). Wenn y kleiner als ein bestimmter Schwellenwert (z. B. 0,05) ist und die Verteilung der Nicht-Null-Elemente unregelmäßig ist, wird die Matrix als spärliche Matrix bezeichnet , andernfalls als dichte Matrix .

Um Speicherplatz zu sparen, kann beim Speichern dünn besetzter Matrizen eine komprimierte Speichermethode verwendet werden, die nur Elemente ungleich Null speichert. Um die komprimierte und gespeicherte Matrix auf die ursprüngliche Matrix wiederherzustellen, muss beim Speichern von Elementen ungleich Null nicht nur der Wert des Elements gespeichert werden, sondern auch sein Speicherort, dh die Speicherinformationen jedes Elements ungleich Null sollte ein Triplett (i, j, aij) sein, i und j sind die Zeilen- bzw. Spaltenpositionen des Elements aij.

Da die Anzahl der Elemente der komprimierten Sparse-Matrix normalerweise viel kleiner ist als die Anzahl der Elemente der Originalmatrix, ist die Operationseffizienz der komprimierten Koeffizientenmatrix höher als die der Originalmatrix. Im Folgenden wird zur Veranschaulichung die Transponierungsoperation für die komprimierte Sparse-Matrix als Beispiel verwendet.

Die Transponierungsoperation der Matrix ruft tatsächlich die Zeilennummern und Spaltennummern aller Elemente der Matrix auf. Daher reicht es für die komprimierte Sparse-Matrix sm aus, die Zeilennummern und Spaltennummern jedes Elements in sm auszutauschen .nz, aber der Austausch Die Sortierung der Elemente in sm.nz erfüllt nicht die Anforderungen der Zeilen zuerst und der Spalten nach dem Ersetzen. Der einfachste Weg, damit umzugehen, besteht darin, sm.nz zu sortieren, also nach den Sortierregeln zu sortieren Bereits in der Struktur smNode definiert, rufen Sie einfach den Algorithmus in STL auf. Einfach sortieren.

//矩阵的类型定义
constexpr auto M = 100; //矩阵行数的上限
constexpr auto N = 100; //矩阵列数的上限
typedef int datatype;
struct matrix {
	datatype a[M][N];
	int row; //矩阵的行数
	int col; //矩阵的列数
	matrix(int r = 0, int c = 0) :row(r), col(c) {
		memset(a, 0, sizeof(a));
	}
	matrix(datatype b[M][N], int r, int c) :row(r), col(c) { //用数组b初始化当前矩阵
		for (int i = 0; i < r; i++)
			for (int j = 0; j < c; j++)
				a[i][j] = b[i][j];
	}
};

//两个矩阵相乘,mat1*mat2,相乘结果作为返回值
matrix mat(matrix mat1, matrix mat2) {
	if (mat1.col != mat2.col) {
		cout << "矩阵不能相乘!" << endl;
		return NULL;
	}
	matrix mat(mat1.row, mat2.col); //mat的行数和列数分别mat1的行数和mat2的列数
	for (int i = 0; i < mat1.row; i++) {
		for (int j = 0; j < mat1.col; j++) {
			mat.a[i][j] = 0;
			for (int k = 0; k < mat1.col; k++) {
				mat.a[i][j] += mat1.a[i][k] * mat2.a[k][j];
			}
		}
	}
	return mat;
}


//稀疏矩阵压缩存储的类型定义
struct smNode
{
	int r, c;  //非零元素所在的行号和列号
	datatype data; //非零元素的值
	bool operator<(smNode sm)const { //排序规则:行先列后,从小到大依次排列。
		if (r == sm.r) return c < sm.c;
		return r < sm.r;
	}
};

struct sMatrix {
	smNode nz[N]; //存放所有非零元素
	int n, row, col; //n:非零元素的数量;row:原矩阵的行数;col:原矩阵的列数
	sMatrix() :n(0), row(0), col(0) {
	}
};

//稀疏矩阵的压缩与还原
//将稀疏矩阵mat压缩存储,结果作为返回值
sMatrix sm_convert(matrix mat) {
	sMatrix sm;
	sm.row = mat.row = mat.col;
	for (int i = 0; i < mat.row; i++) {
		for (int j = 0; j < mat.col; j++) {
			if (mat.a[i][j] != 0) { //非零元素加入结果
				int& idx = sm.n; //idx为引用类型
				sm.nz[idx++] = { i,j,mat.a[i][j] };
			}
		}
	}
}

//将压缩存储的稀疏矩阵sm还原为原矩阵
matrix sm_convert(sMatrix sm) {
	matrix mat(sm.row, sm.col);
	for (int i = 0; i < sm.n; i++) {
		smNode tmp = sm.nz[i]; //第i个非零元素
		mat.a[tmp.r][tmp.c] = tmp.data;
	}
	return mat;
}

//压缩稀疏矩阵的转置
//求压缩稀疏矩阵的转置,结果也为压缩稀疏矩阵并作为返回值
sMatrix sm_tr(sMatrix sm) {
	sMatrix ret;
	ret.row = sm.col, ret.col = sm.row, ret.n = sm.n;//转置后的函数和列数与原矩阵交换,非零元素的数量不变
	for (int i = 0; i < sm.n; i++) { //考虑每一个非零元素
		smNode tmp = sm.nz[i];
		ret.nz[i] = { tmp.c,tmp.r,tmp.data }; //颠换行列
	}
	sort(ret.nz, ret.nz + ret.n); //将元素按指定的顺序排列
	return ret;
}

Je suppose que tu aimes

Origine blog.csdn.net/qq_62687015/article/details/128588675
conseillé
Classement