稀疏矩阵的顺序存储结构表示

稀疏矩阵的顺序存储结构表示

完整代码可到CSDN资源中搜索顺序存储空间表示的稀疏矩阵的创建和矩阵运算进行下载。
稀疏矩阵:在数值分析中经常出现一些阶数很高的矩阵,同时在矩阵中有许多相同的元素或者是零元素。假若值相同的元素或者零元素在矩阵中的分布没有一定的规律,我们称此类矩阵为稀疏矩阵。为了节约存储空间,对零元不分配空间,只存储稀疏矩阵的非零元。用一个三元组(i,j, a ij )唯一确定了矩阵的一个非零元。由此,稀疏矩阵可以由表示非零元的三元组和矩阵的行列数唯一确定。为了计数方便,我们再增加一个参数表示非零元个数。基本数据结构如下:
typedef int ElemType;       //矩阵的数据类型
typedef struct{   //三元组
	int row;    //此处的行列值为真实值,都从1开始没有第0行和第0列
	int col; 
	ElemType value;   //矩阵第row行第col列对应的值
}Triple;

typedef struct{      //矩阵的类型
	Triple *data; //非零三元组表
	int row_num;      //矩阵的总行数
	int col_num;	//矩阵的总列数
	int non_zero;	//矩阵总的非零值的个数
}TSMatrix;



1、创建一个稀疏矩阵:顺序存储结构,则此时需要的参数有:矩阵的总行数、总列数、非零元的总个数、以及非零元对应的三元组(i,j,aij)。因此在该函数中要做到:
(1)提示用户输入矩阵matrix的总行数row_num,总列数col_num,以及非零元non_zero的总个数 ,并赋给矩阵的相应参数
(2)为矩阵matrix分配non_zero个Triple类型的内存空间并提示用户输入non_zero个三元组,将输入的三元组安输入顺序存放在数据区

(3)输入结束后对三元组用冒泡法按照行列号进行重排序,使行列号小的在前,行列号大的在后。并且若出现行列号相同的情况,说明前后两次输入了同样的行列号,会造成数据冲突,此时ReorderSMtrix返回FALSE,表示排序失败,创建矩阵也就失败,否则放回TRUE表示排序成功。

//冒泡法排序
int ReorderSMatrix( TSMatrix *matrix1 )
{
	int i;
	int j;
	Triple temp;
		
	for( i = 0; i < matrix1->non_zero - 1; i++ ){
		for( j = 0; j < matrix1->non_zero - 1 - i; j++ ){
			if( ( matrix1->data + j )->row > ( matrix1->data + j + 1 )->row ){  //先按照行号进行排序,非递减排序
				temp = *( matrix1->data + j );
				*( matrix1->data + j ) = *( matrix1->data + j + 1 );
				*( matrix1->data + j + 1 ) = temp;
			}
			else if( ( matrix1->data + j )->row == ( matrix1->data + j + 1 )->row ){  //行号相等时按照列号进行排序,非递减排序
				if( ( matrix1->data + j )->col > ( matrix1->data + j + 1 )->col ){
					temp = *( matrix1->data + j );
					*( matrix1->data + j ) = *( matrix1->data + j + 1 );
					*( matrix1->data + j + 1 ) = temp;
				}
				else if( ( matrix1->data + j )->col == ( matrix1->data + j + 1 )->col ){  //若行列好均相等,则返回FALSE
					return FALSE;
				}
			}
		}
	}
	return TRUE; 
}

void CreateSMatrix( TSMatrix *matrix )
{
	int i;


	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 );
	}
	matrix->data = ( Triple *)malloc( sizeof( Triple ) * matrix->non_zero );   //为矩阵的实际存储数据的单元分配内存空间
	if( !matrix->data ){  //分配存储空间失败,报错并结束程序执行
		printf( " CreateSMatrix Error: OVERFLOW\n" );
		exit( EXIT_FAILURE );
	}
	printf( "make sure: 0row_num, matrix->col_num ); 
	for( i = 0; i < matrix->non_zero; i++ ){   //分配存储空间成功,以(行,列,值)的形式逐个输入矩阵的值
		printf( "please input the (row, colum,value) of the %d none zero element of the matrix:\n", i + 1 ); 
		scanf( "%d,%d,%d", &( matrix->data + i )->row, &( matrix->data + i )->col, &( matrix->data + i )->value );
		if( ( matrix->data + i )->row <= 0 || ( matrix->data + i )->row > matrix->row_num //当输入的行列值不满足条件时
			|| ( matrix->data + i )->col > matrix->col_num || ( matrix->data + i )->col <= 0 ){
			printf( "CreateSMatrix Error:wrong input of row or col\n" );   //打印错误并结束程序执行
			exit( EXIT_FAILURE );
		}
	}

	if( !ReorderSMatrix( matrix ) ){
		printf( "CreateSMatrix Error:different elements have the same row and colum\n" );
		exit( EXIT_FAILURE );
	}

2、矩阵加减法:在进行矩阵加减法时,由于两个矩阵的非零元的行列号可能相等也可能不等,因此在计算开始之前为结果矩阵分配空间时无法确定结果矩阵中的非零元的个数,因此只能按最大的可能进行分配,即分配总行数*总列数个三元组类型的内存单元。加减法的算法复杂度为两个相加矩阵的非零元的总个数。运算结束之后,可以得到结果矩阵的非零元的总个数。为了节约存储空间,对结果矩阵使用realloc重新分配空间。

//当两个矩阵行列值相同时,对其进行加法运算,并将相加的结果存储到result中
void AddSMatrix( TSMatrix *matrix1, TSMatrix *matrix2, TSMatrix *result )
{
	int i = 0;
	int j = 0;
	int k = 0;
	if( matrix1->row_num != matrix2->row_num || matrix1->col_num != matrix2->col_num ){  //如果两个矩阵的行数或者列数不相同
		printf( "AddSMatrix Error: the row or the colum of the matrixs is different!\n" );
	}
	else{   //否则为结果矩阵分配内存空间
		result->data = ( Triple *)malloc( sizeof( Triple ) * ( matrix1->row_num * matrix1->col_num ) ); 
		if( !result->data )   //分配失败,则报错
			printf( "AddSMatrix Error:OVERFLOW!\n" );
		else{         //分配空间成功
			result->row_num  = matrix1->row_num;//设置结果矩阵的行列值
			result->col_num  = matrix1->col_num;
			while( i < matrix1->non_zero && j < matrix2->non_zero ){ //当两个矩阵的元素都没有处理完时对两个矩阵从第一个元素开始进行加法运算
				if( ( matrix1->data + i )->row < ( matrix2->data + j )->row ){//如果第一个矩阵的第i个元素的行号小于第二个矩阵的第j个元素的行号
					*( result->data + k ) = *( matrix1->data + i );//将第一个矩阵的第i个元素赋给结果矩阵的第k项
					i++;
					k++;
				}
				else if( ( matrix1->data + i )->row == ( matrix2->data + j )->row ){//如果第一个矩阵的第i个元素的行号等于第二个矩阵的第j个元素的行号
					if( ( matrix1->data + i )->col < ( matrix2->data + j )->col ){//继续比较两个矩阵元素的列号,如果第一个矩阵的第i个元素的列号小于第二个矩阵的第j个元素的列号
						*( result->data + k ) = *( matrix1->data + i );   //将第一个矩阵的第i个元素赋给结果矩阵的第k项
						i++;
						k++;
					}										
					else if( ( matrix1->data + i )->col == ( matrix2->data + j )->col ){//如果两个矩阵元素的行列值均相等
						( result->data + k )->row = ( matrix1->data + i )->row;//结果矩阵的行列值与任一个矩阵的行列相同
						( result->data + k )->col = ( matrix1->data + i )->col;
						( result->data + k )->value = ( matrix1->data + i )->value + ( matrix2->data + j )->value;//则结果矩阵元素的value项为两个矩阵元素对应的value项的和
						i++;
						j++;
						k++;
					}
					else{	//如果第一个矩阵的第i个元素的列号大于第二个矩阵的第j个元素的列号且行号相同
						*( result->data + k ) = *( matrix2->data + j );  //将第二个矩阵的第j个元素赋给结果矩阵的第k项
						j++;
						k++;
					}
				}
				else{//如果第一个矩阵的第i个元素的行号大于第二个矩阵的第j个元素的行号
					*( result->data + k ) = *( matrix2->data + j ); //将第二个矩阵的第j个元素赋给结果矩阵的第k项
					j++;
					k++;
				}
			}
		}
		if( i >= matrix1->non_zero ){   //如果先对第一个矩阵的元素处理完毕
			for( ;j < matrix2->non_zero; j++ ){//直接将第二个矩阵剩余的元素赋给结果矩阵的项
				*( result->data + k ) = *( matrix2->data + j );
				k++;
			}
		}
		else if( j >= matrix2->non_zero ){ //如果先对第二个矩阵的元素处理完毕
			for( ;i < matrix1->non_zero; i++ ){//直接将第一矩阵剩余的元素赋给结果矩阵的项
				*( result->data + k ) = *( matrix1->data + i );
				k++;
			}
		}
		result->non_zero = k;  //k的最终结果即为结果矩阵的非零值的个数
	}
}
减法的函数与加法几乎一样,只需要修改将矩阵value赋值的一些地方的加号改成减号即可。

3、复制

//由稀疏矩阵source复制得到dest 
void CopySMatrix( TSMatrix *source, TSMatrix *dest )
{
	int i;
	
	dest->data = ( Triple *)malloc( sizeof( Triple ) * source->non_num ); 
	if( !dest->data ){  //分配存储空间失败,报错并结束程序执行
		printf( " CopySMatrix Error: OVERFLOW\n" );
		exit( EXIT_FAILURE );
	}
	
	dest->row_num = source->row_num;
	dest->col_num = source->col_num;
	dest->non_zero = source->non_zero;
	for( i = 0; i < source->non_zero; i++ ){   //分配存储空间成功,以(行,列,值)的形式逐个输入矩阵的值
		*( dest->data + i ) = *( source->data + i );
	}
}


你可能感兴趣的:(数组)