Structure de données C code 5 : matrice 2D et multiplication matricielle et transposition de matrice compressée

Objectif d'apprentissage : Swing !

Guide d'étude: tableau bidimensionnel du code de Fanshen et multiplication matricielle et transposition de la matrice compressée

Tâches d'apprentissage :

  1. copier le code
  2. Catalogue des résultats d'apprentissage

    1 Structure de données C code 5.1 : Tableau à deux dimensions et multiplication matricielle

    1.1 Tous les codes

    1.2 Résultats des tests

    2 Structures de données C Code 5.2 : transposée de la matrice compressée

    2.1 Tous les codes

    2.2 Résultats des tests

Description du code :

1 Tableau bidimensionnel et multiplication matricielle

        1.1 Ici, un tableau à deux dimensions est utilisé pour représenter la matrice.

        1.2 Deux schémas d'allocation d'espace
        1.3 La complexité de multiplication de la matrice est O(mnk)
        1.4 Vous pouvez connaître sa méthode de stockage en imprimant l'adresse.

2 Transposer la matrice compressée

        2.1 C'est un peu gênant de lire les données, ça devrait être plus facile si elles existent dans le fichier.

        2.2 La complexité temporelle de la transposition est faible.

        2.3 Au départ, je voulais écrire une autre multiplication, oubliez-la, les élèves capables l'exploreront par eux-mêmes. Mais il convient de noter qu'après avoir multiplié deux matrices creuses, ce n'est généralement pas une matrice creuse, donc le résultat n'a pas besoin d'être stocké dans un matrice compressée En même temps, il devrait être dans Un autre tableau de décalages est défini dans la structure, ce qui est pratique pour le positionnement et le calcul.

temps d'étude:

2022.5.19

1 Structure de données C code 5.1 : Tableau à deux dimensions et multiplication matricielle

1.1 Tous les codes

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>

#define ROWS 4
#define COLUMNS 5
/**
 * 动态二维数组 定义1
 */
typedef struct TwoDArray{
	int rows;
	int columns;
	int** elements;
} TwoDArray, *TwoDArrayPtr;
/**
 * 静态二维数组 定义2
 */
typedef struct TwoDStaticArray{
	int rows;
	int columns;
	int elements[ROWS][COLUMNS];
} TwoDStaticArray, *TwoDStaticArrayPtr;

/**
 * @brief 初始化动态二维数组。
 * 
 * @param paraColumns 
 * @param paraRows 
 * 
 * @return 
 */
TwoDArrayPtr initTwoDArray(int paraRows, int paraColumns){
	int i;
	TwoDArrayPtr resultPtr = (TwoDArrayPtr)malloc(sizeof(struct TwoDArray));
	resultPtr->rows = paraRows;
	resultPtr->columns = paraColumns;
	resultPtr->elements = (int**)malloc(paraRows * sizeof(int*));
	for (i = 0; i < paraRows; i ++){
		resultPtr->elements[i] = (int*)malloc(paraColumns * sizeof(int));
	}
	
	return resultPtr;
}
/**
 * @brief 随机化数组的数据。
 * 
 * @param paraLowerBound 
 * @param paraPtr 
 * @param paraUpperBound 
 */
void randomizeTwoDArray(TwoDArrayPtr paraPtr, int paraLowerBound, int paraUpperBound){
	int i, j;	
	for (i = 0; i < paraPtr->rows; i ++){
		for (j = 0; j < paraPtr->columns; j ++) {
			paraPtr->elements[i][j] = rand() % (paraUpperBound - paraLowerBound) + paraLowerBound;
		}
	}
}

/**
 * @brief 打印二维数组
 * 
 * @param paraPtr 
 */
void printTwoDArray(TwoDArrayPtr paraPtr){
	int i, j;	
	for (i = 0; i < paraPtr->rows; i ++){
		for (j = 0; j < paraPtr->columns; j ++) {
			printf("%d, ", paraPtr->elements[i][j]);
		}
		printf("\n");
	}
}

/**
 * @brief 矩阵乘法。
 * 
 * @param paraPtr1 
 * @param paraPtr2 
 * 
 * @return 
 */
TwoDArrayPtr matrixMultiply(TwoDArrayPtr paraPtr1, TwoDArrayPtr paraPtr2){
	int i, j, k, sum;
	if (paraPtr1->columns != paraPtr2->rows){
		printf("矩阵不能相乘.\n");
		return NULL;
	}
	
	TwoDArrayPtr resultPtr = initTwoDArray(paraPtr1->rows, paraPtr2->columns);
	
	for (i = 0; i < paraPtr1->rows; i ++){
		for (j = 0; j < paraPtr2->columns; j ++) {
			sum = 0;
			for (k = 0; k < paraPtr1->columns; k ++) {
				sum += paraPtr1->elements[i][k] * paraPtr2->elements[k][j];
			}
			resultPtr->elements[i][j] = sum;
		}
	}
	
	return resultPtr;
}

/**
 * @brief 测试二维数组的生成。
 */
void twoDArrayTest(){
	printf("---- twoDArrayTest 测试开始 ----\n");
	TwoDArrayPtr tempPtr1, tempPtr2, tempPtr3;
	tempPtr1 = initTwoDArray(3, 2);
	randomizeTwoDArray(tempPtr1, 1, 5);
	printf("第一个矩阵:\n");
	printTwoDArray(tempPtr1);
	
	tempPtr2 = initTwoDArray(2, 4);
	randomizeTwoDArray(tempPtr2, 4, 9);
	printf("第二个矩阵:\n");
	printTwoDArray(tempPtr2);
	
	tempPtr3 = matrixMultiply(tempPtr1, tempPtr2);
	printf("乘积结果:\n");
	printTwoDArray(tempPtr3);
	printf("---- twoDArrayTest 测试结束 ----\n\n");
}

/**
 * @brief 初始化静态二维数组,并打印地址。
 * 
 * @return 
 */
TwoDStaticArrayPtr initTwoDStaticArray(){
		printf("---- initTwoDStaticArray 测试开始 ----\n");
	int i, j;
	TwoDStaticArrayPtr resultPtr = (TwoDStaticArrayPtr)malloc(sizeof(struct TwoDStaticArray));
	resultPtr->rows = ROWS;
	resultPtr->columns = COLUMNS;
	printf("矩阵数组的地址为:\n");
	for (i = 0; i < ROWS; i ++){
		for (j = 0; j < COLUMNS; j ++) {
			resultPtr->elements[j][i] = j * 10 + i;
			//打印地址
			printf("(%d,%d):%d;   ", j, i, &(resultPtr->elements[j][i]));
		}
		printf("\n");
	}
			printf("---- initTwoDStaticArray 测试结束 ----\n");
	return resultPtr;

}
int main(){
	twoDArrayTest();
	TwoDStaticArrayPtr tempPtr = initTwoDStaticArray();	
	return 1;
}

1.2 Résultats des tests

---- twoDArrayTest 测试开始 ----
第一个矩阵:
2, 4,
3, 1,
2, 1,
第二个矩阵:
7, 7, 6, 8,
4, 4, 5, 6,
乘积结果:
30, 30, 32, 40,
25, 25, 23, 30,
18, 18, 17, 22,
---- twoDArrayTest 测试结束 ----

---- initTwoDStaticArray 测试开始 ----
矩阵数组的地址为:
(0,0):1090919208;   (1,0):1090919228;   (2,0):1090919248;   (3,0):1090919268;   (4,0):1090919288;
(0,1):1090919212;   (1,1):1090919232;   (2,1):1090919252;   (3,1):1090919272;   (4,1):1090919292;
(0,2):1090919216;   (1,2):1090919236;   (2,2):1090919256;   (3,2):1090919276;   (4,2):1090919296;
(0,3):1090919220;   (1,3):1090919240;   (2,3):1090919260;   (3,3):1090919280;   (4,3):1090919300;
---- initTwoDStaticArray 测试结束 ----

2 Structures de données C Code 5.2 : transposée de la matrice compressée

2.1 Tous les codes

#include <stdio.h>
#include <malloc.h>

typedef int elem;
/**
 * 行索引、列索引和数据的三元组。
 */
typedef struct Triple {
	int i;
	int j;
	elem e;
} Triple, *TriplePtr;

/**
 * 行索引、列索引和数据的三元组。
 */
typedef struct CompressedMatrix {
	int rows, columns, numElements;
	Triple* elements;
} CompressedMatrix, *CompressedMatrixPtr;

/**
 * @brief 初始化一个压缩矩阵。
 *
 * @param paraColumns
 * @param paraData
 * @param paraElements
 * @param paraRows
 *
 * @return
 */
CompressedMatrixPtr initCompressedMatrix(int paraRows, int paraColumns, int paraElements, int** paraData) {
	int i;
	//申请一个矩阵
	CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(struct CompressedMatrix));
	resultPtr->rows = paraRows;
	resultPtr->columns = paraColumns;
	resultPtr->numElements = paraElements;
	//申请矩阵的存储库
	resultPtr->elements = (TriplePtr)malloc(paraElements * sizeof(struct Triple));
	//把二维数组的值存入矩阵存储库中
	for (i = 0; i < paraElements; i ++) {
		resultPtr->elements[i].i = paraData[i][0];
		resultPtr->elements[i].j = paraData[i][1];
		resultPtr->elements[i].e = paraData[i][2];
	}

	return resultPtr;
}

/**
 * @brief 打印矩阵
 *
 * @param paraPtr
 */
void printCompressedMatrix(CompressedMatrixPtr paraPtr) {
	int i;
	for (i = 0; i < paraPtr->numElements; i ++) {
		printf("(%d, %d): %d\n", paraPtr->elements[i].i, paraPtr->elements[i].j, paraPtr->elements[i].e);
	}
}

/**
 * @brief 转置一个压缩矩阵。
 *
 * @param paraPtr
 *
 * @return
 */
CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr paraPtr) {
	
	//第一步,分配空间。
	int i, tempColumn, tempPosition;
	int *tempColumnCounts = (int*)malloc(paraPtr->columns * sizeof(int));
	int *tempOffsets = (int*)malloc(paraPtr->columns * sizeof(int));
	for (i = 0; i < paraPtr->columns; i ++) {
		tempColumnCounts[i] = 0;
	}

	CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(struct CompressedMatrix));
	resultPtr->rows = paraPtr->columns;
	resultPtr->columns = paraPtr->rows;
	resultPtr->numElements = paraPtr->numElements;

	resultPtr->elements = (TriplePtr)malloc(paraPtr->numElements * sizeof(struct Triple));

	//第2步,一次扫描以计算转置后的值。
	printf("需要转置,定义tempOffsets[]存储需要转置的值\n");
	for (i = 0; i < paraPtr->numElements; i ++) {
		tempColumnCounts[paraPtr->elements[i].j] ++;
	}
	tempOffsets[0] = 0;
	for (i = 1; i < paraPtr->columns; i ++) {
		tempOffsets[i] = tempOffsets[i - 1] + tempColumnCounts[i - 1];
		printf("tempOffsets[%d] = %d \n", i, tempOffsets[i]);
	}

	//第三步,再次扫描填充数据。
	for (i = 0; i < paraPtr->numElements; i ++) {
		tempColumn = paraPtr->elements[i].j;
		tempPosition = tempOffsets[tempColumn];
		resultPtr->elements[tempPosition].i = paraPtr->elements[i].j;
		resultPtr->elements[tempPosition].j = paraPtr->elements[i].i;
		resultPtr->elements[tempPosition].e = paraPtr->elements[i].e;

		tempOffsets[tempColumn]++;
	}

	return resultPtr;
}

/**
 * @brief 测试压缩矩阵。
 */
void compressedMatrixTest() {
	printf("---- transposeCompressedMatrix 测试开始 ----\n");
	CompressedMatrixPtr tempPtr1, tempPtr2;
	int i, j, tempElements;

	//构造第一个样本矩阵。
	tempElements = 4;
	int** tempMatrix1 = (int**)malloc(tempElements * sizeof(int*));
	for (i = 0; i < tempElements; i ++) {
		tempMatrix1[i] = (int*)malloc(3 * sizeof(int));
	}

	int tempMatrix2[5][3] = {
   
   {0, 0, 2}, {0, 2, 3}, {2, 0, 5}, {2, 1, 6}};
	for (i = 0; i < tempElements; i ++) {
		for (j = 0; j < 3; j ++) {
			tempMatrix1[i][j] = tempMatrix2[i][j];
		}
	}

	tempPtr1 = initCompressedMatrix(2, 3, 4, tempMatrix1);

	printf("初始化后:\n");
	printCompressedMatrix(tempPtr1);

	tempPtr2 = transposeCompressedMatrix(tempPtr1);
	printf("转置后:\n");
	printCompressedMatrix(tempPtr2);
	printf("---- transposeCompressedMatrix 测试结束 ----\n");
}

int main() {
	compressedMatrixTest();
	return 1;
}

2.2 Résultats des tests

---- transposeCompressedMatrix 测试开始 ----
初始化后:
(0, 0): 2
(0, 2): 3
(2, 0): 5
(2, 1): 6
需要转置,定义tempOffsets[]存储需要转置的值
tempOffsets[1] = 2
tempOffsets[2] = 3
转置后:
(0, 0): 2
(0, 2): 5
(1, 2): 6
(2, 0): 3
---- transposeCompressedMatrix 测试结束 ----

Guess you like

Origin blog.csdn.net/qq_61649579/article/details/124861320