第一首先是矩阵乘法
#include#include typedef struct TwoDArray{ int rows; int columns; int **elements; } TwoDArray, *TwoDArrayPtr; typedef struct TwoDStaticArray{ int rows; int columns; int elements[4][5]; } TwoDStaticArray, *TwoDStaticArrayPtr; TwoDArrayPtr initTwoDArray(int paraRows, int paraColumns) { int i; TwoDArrayPtr resultPtr = (TwoDArrayPtr)malloc(sizeof(TwoDArray)); resultPtr->rows = paraRows; resultPtr->columns = paraColumns; resultPtr->elements = (int **)malloc(sizeof(int *) * paraRows); for (i = 0; i < paraRows; i ++) { resultPtr->elements[i] = (int *)malloc(sizeof(int) * paraColumns); } return resultPtr; } 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; } } } 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"); } } TwoDArrayPtr matrixMultiply(TwoDArrayPtr paraPtr1, TwoDArrayPtr paraPtr2) { int i, j, k, sum; if (paraPtr1->columns != paraPtr2->rows) { printf("Matrices cannot be multiplied.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; printf("sum = %d, ", sum); } printf("n"); } return resultPtr; } void twoDArrayTest() { TwoDArrayPtr tempPtr1, tempPtr2, tempPtr3; tempPtr1 = initTwoDArray(3, 2); randomizeTwoDArray(tempPtr1, 1, 5); printf("The first matrix:n"); printTwoDArray(tempPtr1); tempPtr2 = initTwoDArray(2, 4); randomizeTwoDArray(tempPtr2, 4, 9); printf("The second matrix:n"); printTwoDArray(tempPtr2); tempPtr3 = matrixMultiply(tempPtr1, tempPtr2); printf("The result:n"); printTwoDArray(tempPtr3); } TwoDStaticArrayPtr initTwoDStaticArray() { int i, j; TwoDStaticArrayPtr resultPtr = (TwoDStaticArrayPtr)malloc(sizeof(TwoDStaticArray)); resultPtr->rows = 4; resultPtr->columns = 5; for (i = 0; i < 4; i ++) { for (j = 0; j < 5; j ++) { resultPtr->elements[i][j] = i * 10 + j; printf("(%d, %d): %pn", i, j, &(resultPtr->elements[i][j])); } } return resultPtr; } int main() { twoDArrayTest(); TwoDStaticArrayPtr tempPtr = initTwoDStaticArray(); return 0; }
运行结果
The first matrix: 2, 4, 3, 1, 2, 1, The second matrix: 7, 7, 6, 8, 4, 4, 5, 6, sum = 30, sum = 30, sum = 32, sum = 40, sum = 25, sum = 25, sum = 23, sum = 30, sum = 18, sum = 18, sum = 17, sum = 22, The result: 30, 30, 32, 40, 25, 25, 23, 30, 18, 18, 17, 22, (0, 0): 00000000001E15B8 (0, 1): 00000000001E15BC (0, 2): 00000000001E15C0 (0, 3): 00000000001E15C4 (0, 4): 00000000001E15C8 (1, 0): 00000000001E15CC (1, 1): 00000000001E15D0 (1, 2): 00000000001E15D4 (1, 3): 00000000001E15D8 (1, 4): 00000000001E15DC (2, 0): 00000000001E15E0 (2, 1): 00000000001E15E4 (2, 2): 00000000001E15E8 (2, 3): 00000000001E15EC (2, 4): 00000000001E15F0 (3, 0): 00000000001E15F4 (3, 1): 00000000001E15F8 (3, 2): 00000000001E15FC (3, 3): 00000000001E1600 (3, 4): 00000000001E1604
首先是创建了一个静态和一个动态的二维数组,然后通过静态的二维数组可以看到,在内存空间中,二维数组是一行一行存储的
还有动态二维数组在申请空间的时候,首先是给这个整体二维数组申请了空间,然后又给其中的数组申请,给数组申请时,分为两部分,我的理解是第一部分是申请的行,第二部分申请的空间是列,这样就构成一个二维数组了
二、压缩矩阵的转置
核心:转置代码
CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr paraPtr) {
int i, tempColumn, tempPosition;
int *tempColumnCounts = (int *)malloc(sizeof(int) * paraPtr->columns);
int *tempOffsets = (int *)malloc(sizeof(int) * paraPtr->columns);
for (i = 0; i < paraPtr->columns; i ++) {
tempColumnCounts[i] = 0;
}
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix));
resultPtr->rows = paraPtr->columns;
resultPtr->columns = paraPtr->rows;
resultPtr->numElements = paraPtr->numElements;
resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * paraPtr->numElements);
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] = %dn", 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;
}
总代码
#include#include typedef struct Tripe{ int i; int j; int e; } Triple, *TriplePtr; typedef struct CompressedMatrix{ int rows, columns, numElements; TriplePtr elements; } CompressedMatrix, *CompressedMatrixPtr; CompressedMatrixPtr initCompressedMatrix(int paraRows, int paraColumns, int paraElements, int **paraData) { int i; CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix)); resultPtr->rows = paraRows; resultPtr->columns = paraColumns; resultPtr->numElements = paraElements; resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * paraElements); 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; } void printCompressedMatrix(CompressedMatrixPtr paraPtr) { int i; for (i = 0; i < paraPtr->numElements; i ++) { printf("(%d, %d): %dn", paraPtr->elements[i].i, paraPtr->elements[i].j, paraPtr->elements[i].e); } } CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr paraPtr) { int i, tempColumn, tempPosition; int *tempColumnCounts = (int *)malloc(sizeof(int) * paraPtr->columns); int *tempOffsets = (int *)malloc(sizeof(int) * paraPtr->columns); for (i = 0; i < paraPtr->columns; i ++) { tempColumnCounts[i] = 0; } CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix)); resultPtr->rows = paraPtr->columns; resultPtr->columns = paraPtr->rows; resultPtr->numElements = paraPtr->numElements; resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * paraPtr->numElements); 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] = %dn", 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; } void compressedMatrixTest() { CompressedMatrixPtr tempPtr1, tempPtr2; int i, j, tempElements; tempElements = 4; int ** tempMatrix1 = (int **)malloc(sizeof(int *) * tempElements); for (i = 0; i < tempElements; i ++) { tempMatrix1[i] = (int *)malloc(sizeof(int) * 3); } int tempMatrix2[4][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("After initializationn"); printCompressedMatrix(tempPtr1); tempPtr2 = transposeCompressedMatrix(tempPtr1); printf("After transpose.n"); printCompressedMatrix(tempPtr2); } int main() { compressedMatrixTest(); return 0; }
运行结果
After initialization (0, 0): 2 (0, 2): 3 (2, 0): 5 (2, 1): 6 tempOffsets[1] = 2 tempOffsets[2] = 3 After transpose. (0, 0): 2 (0, 2): 5 (1, 2): 6 (2, 0): 3
难点就在于tempColumnCounts和tempOffsets这两个数组
首先是tempColumnCounts,我认为,它就是用来存储原矩阵中不同的列(也就是j)的个数,如测试给出的例子,第0列的有两个,第1列的有一个,第2列的有一个,为什么要用它呢,主要是因为转置后,原矩阵的列就变成了转置矩阵的行,所以在后面排序并转置的过程中,能方便我们使用
然后是tempOffsets这个数组,首先说是这个数组代表什么意思,这个数组其实就是给转置之后的数组,给对应的行(也就是i)的数提供对应的位子,然后每当一个数找到位子后,这个位子就要往后挪一个,因为原位子已经被占了,所以就要+1
tempColumnCounts数组中,第0列的数有2个,变成转置矩阵后,那就是第0行的数了,而第0行的数肯定就是从0号位置开始,而第1列的数有一个,变成转置矩阵后,就是第1行的数,那肯定就是排完第0行的数再来排第1行的数,一行一行的排列,所以在tempOffsets中,第1行的开始位子就是2了,因为第0行占了位子0和1,所以第1行只能从位子2开始排



