typedef int ElemType;
typedef struct OLNode{
int row; //此处的行列值为真实值,都有从1开始没有第0行和第0列
int col;
ElemType value; //矩阵第row行第col列对应的值
struct OLNode *right;
struct OLNode *down;
}OLNode;
typedef struct{
OLNode *rhead; //行链表头指针数组的基地址
OLNode *chead;//列链表头指针数组的基地址
int row_num; //矩阵的总行数
int col_num; //矩阵的总列数
int non_zero; //矩阵总的非零值的个数
}CrossList;
1、由于在运算过程中要多次涉及到矩阵的初始化,因此我们将其写成一个函数方便使用。该函数的功能是:为十字链表型的稀疏矩阵分配行列链表的头指针数组的空间,并将其进行初始化。
int Malloclist( CrossList *matrix )
{
int i;
matrix->rhead = ( OLNode *)malloc( sizeof( OLNode ) * ( matrix->row_num + 1 ) ); //为矩阵的行列链表的头指针分配空间
matrix->chead = ( OLNode *)malloc( sizeof( OLNode ) * ( matrix->col_num +1 ) );
if( !matrix->rhead || !matrix->chead ){ //分配存储空间失败,报错并结束程序执行
return FALSE;
}
for( i = 0; i <= matrix->row_num; i++ ){//对行链表的头进行初始化
( matrix->rhead + i )->right = NULL;
( matrix->rhead + i )->down = NULL;
}
for( i = 0; i <= matrix->col_num; i++ ){//对列链表的头进行初始化
( matrix->chead + i )->right = NULL;
( matrix->chead + i )->down = NULL;
}
return TRUE;
}
//对行链表按列递增的顺序进行排序
void Increse_row( OLNode *List_RHead )
{
OLNode *current;
OLNode *nex;
OLNode *pre;
int count = 0;
int i,j;
current = List_RHead->right;
while( current ){ //统计当前列表的项数
count++;
current = current->right ;
}
for( i = 1; i < count; i++ ){ //冒泡法进行排序
current = List_RHead->right;
pre = List_RHead->right;
for( j = 0; j < count - i; j++ ){
nex = current->right;
if( current->col > nex->col ){
current->right = nex->right;
nex->right= current;
if( current == List_RHead->right ){
List_RHead->right = nex;
pre = List_RHead->right;
}
else{
pre->right = nex;
pre = pre->right;
}
}
else{
pre = current;
current = nex;
}
}
}
}
//将列链表按照行递增的顺序进行排序
void Increse_col( OLNode *List_CHead )
{
OLNode *current;
OLNode *nex;
OLNode *pre;
int count = 0;
int i,j;
current = List_CHead->down;
while( current ){ //统计当前列表的项数
count++;
current = current->down ;
}
for( i = 1; i < count; i++ ){//冒泡法进行排序
current = List_CHead->down;
pre = List_CHead->down;
for( j = 0; j < count - i; j++ ){
nex = current->down;
if( current->row > nex->row ){
current->down = nex->down;
nex->down = current;
if( current == List_CHead->down ){
List_CHead->down = nex;
pre = List_CHead->down;
}
else{
pre->down = nex;
pre = pre->down;
}
}
else{
pre = current;
current = nex;
}
}
}
}
//将current插入到其对应的行链表的合适位置,使行链表的元素按行号递增顺序排列
void Insert_R( OLNode *rhead, OLNode * current )
{
if( ( rhead + current->row )->right == NULL ){
( rhead + current->row )->right = current;
}
else{ //将当前项插入到对应行链表的第一项,并对其进行排序
current->right = ( rhead + current->row )->right;
( rhead + current->row )->right = current;
Increse_row( rhead + current->row );
}
}
//将current插入到其对应的列链表的合适位置,使列链表的元素按列号递增顺序排列
void Insert_C( OLNode *chead, OLNode * current )
{
if( ( chead + current->col )->down == NULL ){
( chead + current->col )->down = current;
}
else{ //将当前项插入到对应行链表的第一项,并对其进行排序
current->down = ( chead + current->col )->down;
( chead + current->col )->down = current;
Increse_col( chead + current->col );
}
}
3、创建稀疏矩阵时我们同样需要矩阵的参数:详见《
稀疏矩阵的顺序存储结构表示
》。
//创建稀疏矩阵,矩阵元素从第一行第一列开始没有第0行和第0列,矩阵的对应值的行列值即为实际的行列值
void CreateSMatrix_OL( CrossList *matrix )
{
int i;
OLNode *current;
printf( "please input the total rows of the matrix:\n" ); //输入矩阵的总行数
scanf( "%d", &matrix->row_num );
printf( "please input the total colums of the matrix:\n" );//输入矩阵的总列数
scanf( "%d", &matrix->col_num );
printf( "please input the total numbers of non_zero elements of the matrix:\n" ); //输入矩阵的非零值的个数
scanf( "%d", &matrix->non_zero );
if( matrix->non_zero > matrix->row_num * matrix->col_num ){ //输入的非零值个数太多报错并结束程序的执行
printf( "CreateSMatrix Error:too much none zero elements\n" );
exit( EXIT_FAILURE );
}
if( !Malloclist( matrix ) ){ //为matrix分配空间,若分配失败报错并结束执行
printf( "CreateSMatrix_OL Error:OVERFLOW!\n" );
exit( EXIT_FAILURE );
}
printf( "make sure: 0row_num, matrix->col_num );
for( i = 0; i < matrix->non_zero; i++ ){ //分配存储空间成功,以(行,列,值)的形式逐个输入矩阵的值
current = ( OLNode * )malloc( sizeof( OLNode ) ); //为一个矩阵项分配空间
if( !current ){ //分配存储空间失败,报错并结束程序执行
printf( "CreateSMatrix Error: OVERFLOW\n" );
exit( EXIT_FAILURE );
}
current->down = NULL; //将current的down和right都初始化为NULL
current->right = NULL;
printf( "please input the (row, colum, value) of the %d none zero element of the matrix:\n", i + 1 );
scanf( "%d,%d,%d", ¤t->row, ¤t->col, ¤t->value );
if( current->row <= 0 || current->row > matrix->row_num || current->col > matrix->col_num || current->col <= 0 ){ //当输入的行列值不满足条件时
printf( "CreateSMatrix Error:wrong input of row or col\n" ); //打印错误并结束程序执行
exit( EXIT_FAILURE );
}
//将current插入到对应的行列链表的合适的位置
Insert_R( matrix->rhead, current );
Insert_C( matrix->chead, current );
}
}
//当第一个矩阵的列值等于第二个矩阵的行值时,对这两个矩阵进行相乘的运算并将结果存在result矩阵中
void MultSMatrix_OL( CrossList *matrix1, CrossList *matrix2, CrossList *result )
{
int i;
int j;
int count;
OLNode *current1;
OLNode *current2;
OLNode *current;
if( matrix1->col_num != matrix2->row_num ){ //如果两个矩阵的行数或者列数不相同
printf( "AddSMatrix Error: the colum of the first matrix and therow of the second matrix is different!\n" );
}
else{
result->row_num = matrix1->row_num;
result->col_num = matrix2->col_num;
if( !Malloclist( result ) ){//为结果矩阵分配内存空间
printf( "CopySMatrix_OL Error:OVERFLOW!\n" );
exit( EXIT_FAILURE );
}
i = 1;
count = 0;
while( i <= matrix1->row_num ){ //对第一个矩阵逐行进行运算
j = 1;
while( j <= matrix2->col_num ){ //用第一个矩阵的第i个行链表的各项依次与第二个矩阵的各个列链表的各项进行合适的运算
current1 = ( matrix1->rhead + i )->right;
current2 = ( matrix2->chead + j )->down;
current = ( OLNode * )malloc( sizeof( OLNode ) ); //为一个矩阵项分配空间
if( !current ){ //分配存储空间失败,报错并结束程序执行
printf( "SubSMatrix_OL Error: OVERFLOW\n" );
exit( EXIT_FAILURE );
}
else{ //分配存储空间成功呢,初始化
current->value = 0;
current->right = NULL;
current->down = NULL;
}
while( current1 && current2 ){ //当第一个矩阵的第i个行链表和第二个矩阵的第j个列链表均没有到达末尾时
if( current1->col == current2->row ) { //如果current1的列号与current2的行号相等
current->row = current1->row; //current1的行号和current2的列号构成结果矩阵项current的行列号
current->col = current2->col;
current->value += current1->value * current2->value;//current1和current2相乘的结果作为current的value值
current1 =current1->right;//继续下一项运算
current2 = current2->down;
}
else if( current1->col < current2->row ) //如果current1的列号小于current2的行号
current1 =current1->right; //取current1的下一项进行比较运算
else //如果current1的列号大于current2的行号
current2 = current2->down; //取current2的下一项进行比较运算
}
if( current->value == 0 ){ //如果current的value的最终结果为0,说明第一个矩阵的第i行中的所有元素的列号都与
free( current ); //第二个矩阵的第j列中的所有元算的行号都不想等,即没有满足相乘条件的项,释放current
}
else{ //如果current的value的最终结果不为0,则将current插入到结果矩阵的合适位置
Insert_R( result->rhead, current );
Insert_C( result->chead, current );
count++; 每插入到结果矩阵中一个矩阵项,count就增加1,用于统计结果矩阵的非零值的个数
}
j++;
}
i++;
}
result->non_zero = count;
}
}