Estructura de datos Código C 5: matriz 2D y multiplicación de matriz y transposición de matriz comprimida

Objetivo de aprendizaje: ¡ Swing!

Guía de estudio: matriz bidimensional del código de Fanshen y multiplicación de matriz y transposición de matriz comprimida

Tareas de aprendizaje:

  1. copiar codigo
  2. Catálogo de resultados de aprendizaje

    1 Estructura de datos Código C 5.1: Matriz bidimensional y multiplicación de matrices

    1.1 Todos los códigos

    1.2 Resultados de la prueba

    2 Estructuras de datos Código C 5.2: transposición de matriz comprimida

    2.1 Todos los códigos

    2.2 Resultados de la prueba

Descripción del código:

1 Arreglos bidimensionales y multiplicación de matrices

        1.1 Aquí se utiliza un arreglo bidimensional para representar la matriz.

        1.2 Dos esquemas de asignación de espacio
        1.3 La complejidad de multiplicación de la matriz es O(mnk)
        1.4 Puede conocer su método de almacenamiento imprimiendo la dirección.

2 Transposición de matriz comprimida

        2.1 Es un poco problemático leer los datos, debería ser más fácil si existe en el archivo.

        2.2 La complejidad del tiempo de transposición es baja.

        2.3 Originalmente quería escribir otra multiplicación, olvídalo, los estudiantes capaces explorarán por sí mismos, pero debe tenerse en cuenta que después de multiplicar dos matrices dispersas, generalmente no es una matriz dispersa, por lo que no es necesario almacenar el resultado en un matriz comprimida Al mismo tiempo, debe estar en Una matriz de compensaciones más está definida en la estructura, lo cual es conveniente para el posicionamiento y el cálculo.

tiempo de estudio:

2022.5.19

1 Estructura de datos Código C 5.1: Matriz bidimensional y multiplicación de matrices

1.1 Todos los códigos

#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 Resultados de la prueba

---- 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 Estructuras de datos Código C 5.2: transposición de matriz comprimida

2.1 Todos los códigos

#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 Resultados de la prueba

---- 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 测试结束 ----

Supongo que te gusta

Origin blog.csdn.net/qq_61649579/article/details/124861320
Recomendado
Clasificación