1、基本结构定义
typedef int elem_type;
typedef struct triplet
{
int r, c;
elem_type elem;
}triplet;
typedef struct sparse_mat
{
triplet * data;
int rows;
int cols;
int n_elem;
}sparse_mat;
2、从数据文件初始化、释放
void init_sparse_mat( sparse_mat * mat, const char * file )
{
FILE * fp = fopen( file, "r+" );
int rows, cols, n_elem = 0;
int i, j, k = 0;
elem_type e;
assert( fp != NULL );
fscanf( fp, "%d %d", &rows, &cols );
mat->rows = rows;
mat->cols = cols;
for( i = 0; i < rows; ++i )
{
for( j = 0; j < cols; ++j )
{
fscanf( fp, "%d", &e );
if( e != 0 )
++n_elem;
}
}
mat->n_elem = n_elem;
//rewind( fp );
fseek( fp, 2 * sizeof( int ), SEEK_SET );
mat->data = ( triplet * )malloc( sizeof( triplet ) * n_elem );
for( i = 0; i < rows; ++i )
{
for( j = 0; j < cols; ++j )
{
fscanf( fp, "%d", &e );
if( e != 0 )
{
mat->data[k].r = i;
mat->data[k].c = j;
mat->data[k].elem = e;
++k;
}
}
}
fclose( fp );
}
void free_sparse_mat( sparse_mat * mat )
{
if( mat->data != NULL )
free( mat->data );
mat->rows = mat->cols = mat->n_elem = 0;
}
3、矩阵转置
void transpose_sparse_mat( sparse_mat * src, sparse_mat * dst )
{
int i, j, k = 0;
dst->rows = src->cols;
dst->cols = src->rows;
dst->n_elem = src->n_elem;
dst->data = ( triplet * )malloc( sizeof( triplet ) * dst->n_elem );
if( dst->n_elem > 0 )
{
for( i = 0; i < src->cols; ++i )
{
for( j = 0; j < src->n_elem; ++j )
{
if( i == src->data[j].c )
{
dst->data[k].r = src->data[j].c;
dst->data[k].c = src->data[j].r;
dst->data[k].elem = src->data[j].elem;
++k;
}
}
}
}
}
4、快速转置
void fast_transpose( sparse_mat * src, sparse_mat * dst )
{
int * ins_pos = NULL, * n_elem = NULL;
int rows = src->rows, cols = src->cols;
int i, j;
dst->rows = cols;
dst->cols = rows;
dst->n_elem = src->n_elem;
if( dst->data != NULL )
free( dst->data );
dst->data = ( triplet * )malloc( sizeof( triplet ) * dst->n_elem );
ins_pos = ( int * )malloc( sizeof( int ) * rows );
n_elem = ( int * )malloc( sizeof( int ) * cols );
memset( ins_pos, 0, sizeof( int ) * cols );
memset( n_elem, 0, sizeof( int ) * cols );
/* first round of scanning */
for( i = 0; i < src->n_elem; ++i )
{
++n_elem[src->data[i].c];
}
ins_pos[0] = 0;
for( i = 1; i < src->cols; ++i )
{
ins_pos[i] = ins_pos[i - 1] + n_elem[i - 1];
}
/* second round of scanning */
for( i = 0; i < src->n_elem; ++i )
{
j = ins_pos[src->data[i].c]++;
dst->data[j].elem = src->data[i].elem;
dst->data[j].r = src->data[i].c;
dst->data[j].c = src->data[i].r;
}
}
5、矩阵的输出
void disp_sparse_mat( sparse_mat * mat )
{
elem_type ** data = NULL;
int rows, cols, i, j;
int r, c;
rows = mat->rows;
cols = mat->cols;
data = ( elem_type ** )malloc( sizeof( elem_type * ) * rows );
for( i = 0; i < rows; ++i )
{
data[i] = ( elem_type * )malloc( sizeof( elem_type ) * cols );
memset( data[i], 0, cols * sizeof( elem_type ) );
}
for( i = 0; i < mat->n_elem; ++i )
{
r = mat->data[i].r;
c = mat->data[i].c;
data[r][c] = mat->data[i].elem;
}
for( i = 0; i < rows; ++i )
{
for( j = 0; j < cols; ++j )
{
printf( "%d ", data[i][j] );
}
printf( "\n" );
}
}
6、完整程序
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef int elem_type;
typedef struct triplet
{
int r, c;
elem_type elem;
}triplet;
typedef struct sparse_mat
{
triplet * data;
int rows;
int cols;
int n_elem;
}sparse_mat;
void init_sparse_mat( sparse_mat * mat, const char * file )
{
FILE * fp = fopen( file, "r+" );
int rows, cols, n_elem = 0;
int i, j, k = 0;
elem_type e;
assert( fp != NULL );
fscanf( fp, "%d %d", &rows, &cols );
mat->rows = rows;
mat->cols = cols;
for( i = 0; i < rows; ++i )
{
for( j = 0; j < cols; ++j )
{
fscanf( fp, "%d", &e );
if( e != 0 )
++n_elem;
}
}
mat->n_elem = n_elem;
//rewind( fp );
fseek( fp, 2 * sizeof( int ), SEEK_SET );
mat->data = ( triplet * )malloc( sizeof( triplet ) * n_elem );
for( i = 0; i < rows; ++i )
{
for( j = 0; j < cols; ++j )
{
fscanf( fp, "%d", &e );
if( e != 0 )
{
mat->data[k].r = i;
mat->data[k].c = j;
mat->data[k].elem = e;
++k;
}
}
}
fclose( fp );
}
void free_sparse_mat( sparse_mat * mat )
{
if( mat->data != NULL )
free( mat->data );
mat->rows = mat->cols = mat->n_elem = 0;
}
void disp_sparse_mat( sparse_mat * mat )
{
elem_type ** data = NULL;
int rows, cols, i, j;
int r, c;
rows = mat->rows;
cols = mat->cols;
data = ( elem_type ** )malloc( sizeof( elem_type * ) * rows );
for( i = 0; i < rows; ++i )
{
data[i] = ( elem_type * )malloc( sizeof( elem_type ) * cols );
memset( data[i], 0, cols * sizeof( elem_type ) );
}
for( i = 0; i < mat->n_elem; ++i )
{
r = mat->data[i].r;
c = mat->data[i].c;
data[r][c] = mat->data[i].elem;
}
for( i = 0; i < rows; ++i )
{
for( j = 0; j < cols; ++j )
{
printf( "%d ", data[i][j] );
}
printf( "\n" );
}
}
void transpose_sparse_mat( sparse_mat * src, sparse_mat * dst )
{
int i, j, k = 0;
dst->rows = src->cols;
dst->cols = src->rows;
dst->n_elem = src->n_elem;
dst->data = ( triplet * )malloc( sizeof( triplet ) * dst->n_elem );
if( dst->n_elem > 0 )
{
for( i = 0; i < src->cols; ++i )
{
for( j = 0; j < src->n_elem; ++j )
{
if( i == src->data[j].c )
{
dst->data[k].r = src->data[j].c;
dst->data[k].c = src->data[j].r;
dst->data[k].elem = src->data[j].elem;
++k;
}
}
}
}
}
void fast_transpose( sparse_mat * src, sparse_mat * dst )
{
int * ins_pos = NULL, * n_elem = NULL;
int rows = src->rows, cols = src->cols;
int i, j;
dst->rows = cols;
dst->cols = rows;
dst->n_elem = src->n_elem;
if( dst->data != NULL )
free( dst->data );
dst->data = ( triplet * )malloc( sizeof( triplet ) * dst->n_elem );
ins_pos = ( int * )malloc( sizeof( int ) * rows );
n_elem = ( int * )malloc( sizeof( int ) * cols );
memset( ins_pos, 0, sizeof( int ) * cols );
memset( n_elem, 0, sizeof( int ) * cols );
/* first round of scanning */
for( i = 0; i < src->n_elem; ++i )
{
++n_elem[src->data[i].c];
}
ins_pos[0] = 0;
for( i = 1; i < src->cols; ++i )
{
ins_pos[i] = ins_pos[i - 1] + n_elem[i - 1];
}
/* second round of scanning */
for( i = 0; i < src->n_elem; ++i )
{
j = ins_pos[src->data[i].c]++;
dst->data[j].elem = src->data[i].elem;
dst->data[j].r = src->data[i].c;
dst->data[j].c = src->data[i].r;
}
}
int main( int argc, char * argv[] )
{
char file[] = "data.txt";
sparse_mat src, dst, dst2;
dst.data = dst2.data = NULL;
init_sparse_mat( &src, file );
disp_sparse_mat( &src );
printf( "------ general transpose -------\n" );
transpose_sparse_mat( &src, &dst );
disp_sparse_mat( &dst );
printf( "------- fast transpose ---------\n" );
fast_transpose( &src, &dst2 );
disp_sparse_mat( &dst2 );
free_sparse_mat( &src );
free_sparse_mat( &dst );
free_sparse_mat( &dst2 );
}
7、数据文件格式
5 6
0 0 0 0 0 0
1 0 0 0 2 0
0 0 0 3 0 0
4 0 5 0 0 6
0 0 0 0 7 0