压缩矩阵及其转置
压缩矩阵
矩阵,即二维数组,其可以采用顺序存储结构来存储其中的元素,但当矩阵阶数很高同时矩阵中有很多值相同的元素(或大多数元素的值为0
)时,采用严格的顺序存储结构显然是相当浪费空间的,因为存储0
元素或许多值相同的元素是没有意义的,因此为了节省空间,对此类矩阵通常采用压缩存储。
稀疏式矩阵(数值为0
的元素数目远远多于非0
元素数目且非0
元素分布无规律的矩阵)的压缩存储,需要存储:①其中非0
元素的值;②非0
元素在矩阵中的行下标和列下标;③非0
元素的个数;④矩阵总行数和总列数
例如:对图一稀疏矩阵进行压缩其结果如图二所示。
压缩前(图一)
压缩后(图二)


压缩矩阵存储代码
typedef int ElemType;
typedef struct Triple
{
int i; /* 非零元素行下标 */
int j; /* 非零元素列下标 */
ElemType element;
} Triple, *TriplePtr;
typedef struct CompressedMatrix
{
int rows,columns,numElements; /* 行数、列数、非零元素个数 */
TriplePtr elements;
} CompressedMatrix, *CompressedMatrixPtr;
初始化压缩矩阵
/* 初始化压缩矩阵 */
CompressedMatrixPtr initCompressedMatrix(int tempRows, int tempColumns, int tempElements, ElemType** tempData)
{
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix));
resultPtr->rows = tempRows;
resultPtr->columns = tempColumns;
resultPtr->numElements = tempElements;
resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * tempElements);
for(int i = 0; i < tempElements; ++i)
{
resultPtr->elements[i].i = tempData[i][0];
resultPtr->elements[i].j = tempData[i][1];
resultPtr->elements[i].element = tempData[i][2];
}
return resultPtr;
}
压缩矩阵的转置
矩阵转置是矩阵运算中极为重要的操作,但矩阵压缩后我们不能再像原来使用n * m
的方式进行转置操作,此时其转置需要以下三部才能完成:
①将矩阵行数和列数互换
②将三元组表中的i
行和j
列互换
③不断遍历存储矩阵的三元组表,每次取出表中j
列最小的一组,互换行标和列标的值,并按 次序存储到新的三元组表中
代码描述:
/* 转置压缩矩阵 */
CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr tempPtr)
{
int tempColumn,tempPosition;
int* tempColumnCounts = (int*)malloc(tempPtr->columns * sizeof(int));
int* tempOffsets = (int*)malloc(tempPtr->columns * sizeof(int));
for(int i = 0; i < tempPtr->columns; ++i)
{
tempColumnCounts[i] = 0;
}
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix));
resultPtr->rows = tempPtr->columns;
resultPtr->columns = tempPtr->rows;
resultPtr->numElements = tempPtr->numElements;
resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * tempPtr->numElements);
for(int i = 0; i < tempPtr->numElements; ++i)
{
tempColumnCounts[tempPtr->elements[i].j]++;
}
tempOffsets[0] = 0;
for(int i = 1; i < tempPtr->columns; ++i)
{
tempOffsets[i] = tempOffsets[i-1] + tempColumnCounts[i-1];
printf("tempOffsets[%d] = %d \n",i,tempOffsets[i]);
}
for(int i = 0; i < tempPtr->numElements; ++i)
{
tempColumn = tempPtr->elements[i].j;
tempPosition = tempOffsets[tempColumn];
resultPtr->elements[tempPosition].i = tempPtr->elements[i].j;
resultPtr->elements[tempPosition].j = tempPtr->elements[i].i;
resultPtr->elements[tempPosition].element = tempPtr->elements[i].element;
tempOffsets[tempColumn]++;
}
return resultPtr;
}
打印压缩矩阵
/* 打印压缩矩阵 */
void printCompressedMatrix(CompressedMatrixPtr tempPtr)
{
for(int i = 0; i < tempPtr->numElements; ++i)
{
printf("(%d, %d): %d\n",tempPtr->elements[i].i,tempPtr->elements[i].j,tempPtr->elements[i].element);
}
}
完整代码
#include <stdio.h>
#include <malloc.h>
typedef int ElemType;
typedef struct Triple
{
int i; /* 非零元素行下标 */
int j; /* 非零元素列下标 */
ElemType element;
} Triple, *TriplePtr;
typedef struct CompressedMatrix
{
int rows,columns,numElements; /* 行数、列数、非零元素个数 */
TriplePtr elements;
} CompressedMatrix, *CompressedMatrixPtr;
/* 初始化压缩矩阵 */
CompressedMatrixPtr initCompressedMatrix(int tempRows, int tempColumns, int tempElements, ElemType** tempData)
{
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix));
resultPtr->rows = tempRows;
resultPtr->columns = tempColumns;
resultPtr->numElements = tempElements;
resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * tempElements);
for(int i = 0; i < tempElements; ++i)
{
resultPtr->elements[i].i = tempData[i][0];
resultPtr->elements[i].j = tempData[i][1];
resultPtr->elements[i].element = tempData[i][2];
}
return resultPtr;
}
/* 打印压缩矩阵 */
void printCompressedMatrix(CompressedMatrixPtr tempPtr)
{
for(int i = 0; i < tempPtr->numElements; ++i)
{
printf("(%d, %d): %d\n",tempPtr->elements[i].i,tempPtr->elements[i].j,tempPtr->elements[i].element);
}
}
/* 转置压缩矩阵 */
CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr tempPtr)
{
int tempColumn,tempPosition;
int* tempColumnCounts = (int*)malloc(tempPtr->columns * sizeof(int));
int* tempOffsets = (int*)malloc(tempPtr->columns * sizeof(int));
for(int i = 0; i < tempPtr->columns; ++i)
{
tempColumnCounts[i] = 0;
}
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(CompressedMatrix));
resultPtr->rows = tempPtr->columns;
resultPtr->columns = tempPtr->rows;
resultPtr->numElements = tempPtr->numElements;
resultPtr->elements = (TriplePtr)malloc(sizeof(Triple) * tempPtr->numElements);
for(int i = 0; i < tempPtr->numElements; ++i)
{
tempColumnCounts[tempPtr->elements[i].j]++;
}
tempOffsets[0] = 0;
for(int i = 1; i < tempPtr->columns; ++i)
{
tempOffsets[i] = tempOffsets[i-1] + tempColumnCounts[i-1];
printf("tempOffsets[%d] = %d \n",i,tempOffsets[i]);
}
for(int i = 0; i < tempPtr->numElements; ++i)
{
tempColumn = tempPtr->elements[i].j;
tempPosition = tempOffsets[tempColumn];
resultPtr->elements[tempPosition].i = tempPtr->elements[i].j;
resultPtr->elements[tempPosition].j = tempPtr->elements[i].i;
resultPtr->elements[tempPosition].element = tempPtr->elements[i].element;
tempOffsets[tempColumn]++;
}
return resultPtr;
}
/* 测试 */
void compressedMatrixTest()
{
CompressedMatrixPtr tempPtr1, tempPtr2;
int tempElements;
tempElements = 4;
ElemType** tempMatrix1 = (ElemType**)malloc(sizeof(ElemType*) * tempElements);
for(int i = 0; i < tempElements; ++i)
{
tempMatrix1[i] = (ElemType*)malloc(sizeof(ElemType) * 3);
}
int tempMatrix2[4][3] = {{0,0,2},{0,2,3},{2,0,5},{2,1,6}};
for(int i = 0; i < tempElements; ++i)
{
for(int 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);
}
int main()
{
compressedMatrixTest();
return 0;
}
运行结果
初始化后
(0, 0): 2
(0, 2): 3
(2, 0): 5
(2, 1): 6
tempOffsets[1] = 2
tempOffsets[2] = 3
转置后
(0, 0): 2
(0, 2): 5
(1, 2): 6
(2, 0): 3