练习9——稀疏矩阵
1、转置
1.1第一种想法
1.1.1思想:每次从原矩阵中复制一列到新的矩阵中。1)设矩阵列数为cols,对矩阵三元组扫描cols次;2)第k次扫描寻找所有列号为k的项:将其行号变列号、列号变行号,顺次存于转置矩阵三元组中。
1.1.2代码
void SparseMatrix::Transpose(SparseMatrix &b) {
b.Rows=Rows;b.Cols=Cols;b.Terms=Terms;
if(Terms==0)
return ;
int CurrentB=0;
int i,k;
for(k=0;k<Cols;k++){
for(i=0;i<Terms;i++){
if(smArray[i].col==k){
b.smArray[CurrentB].row=k;
b.smArray[CurrentB].col=smArray[i].row;
b.smArray[CurrentB].value=smArray[i].value;
CurrentB++;
}
}
}
}
1.1.3评价:算法的时间代价为O(cols*terms)。如果非零元素变多时,算法的时间代价也会变大。
1.2快速转置算法(推荐)
1.2.1思想:对原矩阵A扫描一遍,按A中每一元素的列号,确定在转置矩阵B中三元组中的位置,并装入它。
1.2.2代码:
void SparseMatrix::FasrTranspos(SparseMatrix &b) {
int *rowSize=new int[Cols];//列元素数数组
int *rowStart=new int[Cols];//转置位置数组
b.Rows=Cols;b.Cols=Rows;b.Terms=Terms;
if(Terms>0){
int i,j;
for(i=0;i<Cols;i++){
rowSize[i]=0;
}
for(i=0;i<Terms;i++){
rowSize[smArray[i].col]++;//记录每列非零元素个数
}
rowStart[0]=0;
for(i=1;i<Cols;i++){
rowStart[i]=rowStart[i-1]+rowSize[i-1];//记录每个元素在三元组中的位置
}
for(i=0;i<Terms;i++){
j=rowStart[smArray[i].col];
b.smArray[j].row=smArray[i].col;
b.smArray[j].col=smArray[i].row;
b.smArray[j].value=smArray[i].value;
rowStart[smArray[i].col]++;
}
}
delete[] rowSize;
delete[] rowStart;
}
1.2.3评价:1)时间复杂度:O(2Cols+2Terms);2);当Terms<<Rows*Cols时,比一般转置算法;3)在空间复杂性上,该算法多用了两个辅助向量,是以少量空间换取了较快的执行速度。
附录(完整代码):
#include <iostream>
using namespace std;
typedef int T;
struct Triple{
int row,col;
T value;
void operator=(Triple &R){
row=R.row;
col=R.col;
value=R.value;
}
};
class SparseMatrix{
private:
int Rows,Cols,Terms;
Triple *smArray;
public:
SparseMatrix(int maxSize=100);
void Transpose(SparseMatrix &b);
void FasrTranspos(SparseMatrix &b);
friend ostream& operator << (ostream &out,SparseMatrix &M);
friend istream& operator >> (istream &in,SparseMatrix &M);
};
SparseMatrix::SparseMatrix(int maxSize) {
Terms=maxSize;
smArray=new Triple[Terms];
if(smArray==NULL){
cerr<<"存储分配失败"<<endl;
exit(1);
}
Rows=Cols=0;
}
//每次从原矩阵中复制一列到新的矩阵中。
// 1)设矩阵列数为cols,对矩阵三元组扫描cols次;
// 2)第k次扫描寻找所有列号为k的项:将其行号变列号、列号变行号,顺次存于转置矩阵三元组中。
void SparseMatrix::Transpose(SparseMatrix &b) {
b.Rows=Rows;b.Cols=Cols;b.Terms=Terms;
if(Terms==0)
return ;
int CurrentB=0;
int i,k;
for(k=0;k<Cols;k++){
for(i=0;i<Terms;i++){
if(smArray[i].col==k){
b.smArray[CurrentB].row=k;
b.smArray[CurrentB].col=smArray[i].row;
b.smArray[CurrentB].value=smArray[i].value;
CurrentB++;
}
}
}
}
void SparseMatrix::FasrTranspos(SparseMatrix &b) {
int *rowSize=new int[Cols];//列元素数数组
int *rowStart=new int[Cols];//转置位置数组
b.Rows=Cols;b.Cols=Rows;b.Terms=Terms;
if(Terms>0){
int i,j;
for(i=0;i<Cols;i++){
rowSize[i]=0;
}
for(i=0;i<Terms;i++){
rowSize[smArray[i].col]++;//记录每列非零元素个数
}
rowStart[0]=0;
for(i=1;i<Cols;i++){
rowStart[i]=rowStart[i-1]+rowSize[i-1];//记录每个元素在三元组中的位置
}
for(i=0;i<Terms;i++){
j=rowStart[smArray[i].col];
b.smArray[j].row=smArray[i].col;
b.smArray[j].col=smArray[i].row;
b.smArray[j].value=smArray[i].value;
rowStart[smArray[i].col]++;
}
}
delete[] rowSize;
delete[] rowStart;
}
ostream & operator<<(ostream &out,SparseMatrix &M){
for(int i=0;i<M.Terms;i++){
out<<M.smArray[i].row<<" "<<M.smArray[i].col<<" "<<M.smArray[i].value<<endl;
}
return out;
}
istream &operator>>(istream &in, SparseMatrix &M) {
in>>M.Rows>>M.Cols>>M.Terms;
for(int i=0;i<M.Terms;i++){
in>>M.smArray[i].row>>M.smArray[i].col>>M.smArray[i].value;
}
return in;
}
int main(){
SparseMatrix s1,s2;
cin>>s1;
cout<<"输入为:"<<endl;
cout<<s1;
s1.FasrTranspos(s2);
cout<<"输出为:"<<endl;
cout<<s2;
}