目录
---这次是压缩数组,其中有数组压缩、压缩数组还原、以及压缩数组的转置。
压缩数组的理解:
为什么需要压缩数组呢?为了节省空间如图:
就是利用数组存储,有效数据所在位置
压缩数组的实现:
代码定义:
typedef struct Triple {//用与记录
int i;
int j;
elem e;
}Triple, *TriplePtr;
typedef struct CompressedMatrix {//压缩数组
int rows, columns, numElements;
Triple* elements;
}CompressedMatrix, *CompressedMatrixPtr;
这里利用的是struct嵌套实现-有名称意义二维数组(numElements * 3), 内嵌的struct便是有类别3个元素 ,分别是行、列、数据。
初始化:
CompressedMatrixPtr initCompressedMatrix(int paraRows, int paraColumns, int paraElements, int** paraData) {
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(struct CompressedMatrix));
resultPtr->columns = paraColumns;
resultPtr->rows = paraRows;
resultPtr->numElements = paraElements;
resultPtr->elements = (TriplePtr)malloc(paraElements * sizeof(struct Triple));
for (int 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];
}//Of for i.
return resultPtr;
}
普通数组转化成压缩:
int** exchangeCompressed(TwoDArrayPtr paraPtr) {
int** resultArray;
resultArray = (int**)malloc(countValuableElement(paraPtr) * sizeof(int*));
for (int i = 0; i < countValuableElement(paraPtr); i++) {
resultArray[i] = (int*)malloc(3 * sizeof(int));
}
int k = 0;
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
if (paraPtr->elements[i][j] != 0) {
resultArray[k][0] = i;
resultArray[k][1] = j;
resultArray[k][2] = paraPtr->elements[i][j];
k++;
}
}
}
return resultArray;
}
其中的的 countValuableElement()数有效数据的个数:
int countValuableElement(TwoDArrayPtr paraPtr) {
int cnt = 0;
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
if (paraPtr->elements[i][j] != 0) {
cnt++;
}
}
}
return cnt;
}
压缩转化为普通数组:
TwoDArrayPtr returnCompressed(CompressedMatrixPtr paraPtr) {
TwoDArrayPtr resultArray = initTwoDArray(paraPtr->rows, paraPtr->columns);
int k = 0;
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
if (paraPtr->elements[k].i == i && paraPtr->elements[k].j == j) {
resultArray->elements[i][j] = paraPtr->elements[k].e;
k++;
} else {
resultArray->elements[i][j] = 0;
}
}
}
return resultArray;
}
压缩数组的转置:
CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr paraPtr) {
//Step 1. 建立记录数组
int *tempColumnCounts = (int*)malloc(paraPtr->columns * sizeof(int));//记录每一列所拥有的数据个数。
int *tempOffsets = (int*)malloc(paraPtr->columns * sizeof(int));//记录列交换后新二维数组的位置
//初始化
for (int i = 0; i < paraPtr->columns; i++) {
tempColumnCounts[i] = 0;//一开始全为 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));
//Step 2.扫描数组
for (int i = 0; i < paraPtr->numElements; i++) {
tempColumnCounts[paraPtr->elements[i].j]++;
}
//Step 3.初始化offset
tempOffsets[0] = 0;
for(int i = 1; i < paraPtr->columns; i++) {
tempOffsets[i] = tempOffsets[i - 1] + tempColumnCounts[i - 1];
}
//Step 4.填入
int tempPosition, tempColumn;
for (int 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]++;
} //Of for i;
return resultPtr;
}
路思:
主要思路就是需要记录转置之前每列的数据个数-tempColumnCounts,然后记录转置之后之前的列在现在行的位置-tempOffsets(随填入而更新的),然后再俩点保障数据再正确位置,另外直接交换压缩数组的行列即可。
总代码:
#include <stdio.h>
#include <malloc.h>
typedef int elem;//
/*
* A trile for row index, colum index, and data.
*/
typedef struct Triple {//用与记录
int i;
int j;
elem e;
}Triple, *TriplePtr;
/**
* A triple for row index, colum index, and data.
*/
typedef struct CompressedMatrix {
int rows, columns, numElements;
Triple* elements;
}CompressedMatrix, *CompressedMatrixPtr;
//稀疏数组
typedef struct TwoDArray{
int rows;
int columns;
int** elements;
}TwoDArray, *TwoDArrayPtr;
TwoDArrayPtr initTwoDArray(int paraRows, int paraColumns){
int i;
TwoDArrayPtr resultPtr = (TwoDArrayPtr)malloc(sizeof(TwoDArray));
resultPtr->columns = paraColumns;
resultPtr->rows = paraRows;
resultPtr->elements = (int**)malloc(sizeof(int*) * paraRows);
for (i = 0; i < paraRows; i++) {
resultPtr->elements[i] = (int*)malloc(sizeof(int) * paraColumns);
}//Of for(i)
return resultPtr;
}
void printTwoDArray(TwoDArrayPtr paraPtr) {
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
printf("%d ", paraPtr->elements[i][j]);
}//Of for i
printf("\r\n");
}//Of for j
}
/**
* Initialize a compressed matrix.
*/
CompressedMatrixPtr initCompressedMatrix(int paraRows, int paraColumns, int paraElements, int** paraData) {
CompressedMatrixPtr resultPtr = (CompressedMatrixPtr)malloc(sizeof(struct CompressedMatrix));
resultPtr->columns = paraColumns;
resultPtr->rows = paraRows;
resultPtr->numElements = paraElements;
resultPtr->elements = (TriplePtr)malloc(paraElements * sizeof(struct Triple));
for (int 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];
}//Of for i.
return resultPtr;
}
/**
* Print the compressed matrix.
*/
void printCompressedMatrix(CompressedMatrixPtr paraPtr) {
for (int i = 0; i < paraPtr->numElements; i++) {
printf("(%d, %d): %d\n", paraPtr->elements[i].i, paraPtr->elements[i].j, paraPtr->elements[i].e);
}//Of for i
}
/**
* Transpose a compressed matrix.
*/
CompressedMatrixPtr transposeCompressedMatrix(CompressedMatrixPtr paraPtr) {
//Step 1. 建立记录数组
int *tempColumnCounts = (int*)malloc(paraPtr->columns * sizeof(int));//记录每一列所拥有的数据个数。
int *tempOffsets = (int*)malloc(paraPtr->columns * sizeof(int));//记录列交换后新二维数组的位置
//初始化
for (int i = 0; i < paraPtr->columns; i++) {
tempColumnCounts[i] = 0;//一开始全为 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));
//Step 2.扫描数组
for (int i = 0; i < paraPtr->numElements; i++) {
tempColumnCounts[paraPtr->elements[i].j]++;
}
//Step 3.初始化offset
tempOffsets[0] = 0;
for(int i = 1; i < paraPtr->columns; i++) {
tempOffsets[i] = tempOffsets[i - 1] + tempColumnCounts[i - 1];
}
//Step 4.填入
int tempPosition, tempColumn;
for (int 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]++;
} //Of for i;
return resultPtr;
}
/*
** test
*/
void compressedMatrixTest(){
printf("--- compressedMatrixTest begins ----\n");
CompressedMatrixPtr tempPtr1, tempPtr2;
int tempElements;
//建立二维数组-动态.
tempElements = 4;
int** tempMatrix1 = (int**)malloc(tempElements * sizeof(int*));
for (int i = 0; i < tempElements; i++) {
tempMatrix1[i] = (int*)malloc(3 * sizeof(int));
}
//初始化
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("After initialization \n");
printCompressedMatrix(tempPtr1);
tempPtr2 = transposeCompressedMatrix(tempPtr1);
printf("After traspose. \n");
printCompressedMatrix(tempPtr2);
printf("--- compressedMatrixTest ends ----\n");
}
int countValuableElement(TwoDArrayPtr paraPtr) {
int cnt = 0;
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
if (paraPtr->elements[i][j] != 0) {
cnt++;
}
}
}
return cnt;
}
int** exchangeCompressed(TwoDArrayPtr paraPtr) {
int** resultArray;
resultArray = (int**)malloc(countValuableElement(paraPtr) * sizeof(int*));
for (int i = 0; i < countValuableElement(paraPtr); i++) {
resultArray[i] = (int*)malloc(3 * sizeof(int));
}
int k = 0;
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
if (paraPtr->elements[i][j] != 0) {
resultArray[k][0] = i;
resultArray[k][1] = j;
resultArray[k][2] = paraPtr->elements[i][j];
k++;
}
}
}
return resultArray;
}
TwoDArrayPtr returnCompressed(CompressedMatrixPtr paraPtr) {
TwoDArrayPtr resultArray = initTwoDArray(paraPtr->rows, paraPtr->columns);
int k = 0;
for (int i = 0; i < paraPtr->rows; i++) {
for (int j = 0; j < paraPtr->columns; j++) {
if (paraPtr->elements[k].i == i && paraPtr->elements[k].j == j) {
resultArray->elements[i][j] = paraPtr->elements[k].e;
k++;
} else {
resultArray->elements[i][j] = 0;
}
}
}
return resultArray;
}
void test() {
printf("---- test begins ----\n");
TwoDArrayPtr tempPtr = initTwoDArray(3, 3);
//稀疏数组初始化
for (int i = 0; i < 3; i++) {
for(int j = 0; j < 3; j++) {
if (i == 0 && j == 0) {
tempPtr->elements[i][j] = 2;
} else if (i == 0 && j == 2) {
tempPtr->elements[i][j] = 3;
} else if (i == 2 && j == 0) {
tempPtr->elements[i][j] = 5;
} else if (i == 2 && j == 1) {
tempPtr->elements[i][j] = 6;
} else {
tempPtr->elements[i][j] = 0;
}
}
}
printf("after init array.\n");
printTwoDArray(tempPtr);
//压缩
int** array = exchangeCompressed(tempPtr);
CompressedMatrixPtr tempCompressedPtr = initCompressedMatrix(tempPtr->rows, tempPtr->columns, countValuableElement(tempPtr), array);
printf("After exchange.\n");
printCompressedMatrix(tempCompressedPtr);
//转置
CompressedMatrixPtr tempCompressedPtr2 = transposeCompressedMatrix(tempCompressedPtr);
printf("After transpose.\n");
printCompressedMatrix(tempCompressedPtr2);
//返回稀疏函数
TwoDArrayPtr tempDAPtr = returnCompressed(tempCompressedPtr2);
printf("After retrun.\n");
printTwoDArray(tempDAPtr);
printf("---- test ends ----\n");
}
int main(void){
compressedMatrixTest();
test();
return 0;
}