数据结构与算法:稀疏矩阵ADT的实现

在现实应用中,一些规模很大的特殊矩阵具有重要的地位。特殊矩阵可以采用二维数组存储,简单直接(顺序存储方式保持了矩阵中元素之间的二维线性关系),矩阵操作的算法都很简单,但是其空间的利用率很低(因为重复元素或零元素比较多)。 稀疏矩阵就是一种应用很广泛的特殊的矩阵,在实现稀疏矩阵ADT时通常采用“压缩”存储方案,即把只存储稀疏矩阵的非零元素,把稀疏矩阵抽象成为一个以三元组(行,列,值)为数据元素的线性表来处理,而我们知道:线性表可以采用顺序存储,也可以采用链式存储(通常用十字链表)。
现要求编程实现稀疏矩阵在“压缩”存储时的常用操作,如输出、转置、求和、乘等。(注:在代码注释中说明你采用的存储结构)
需要输入两个矩阵,完成:
(1) 转置。对第一个矩阵进行转置并输出,前面输出标题 “The transformed matrix is:”
(2) 矩阵加。如两个矩阵可以相加,进行两个矩阵加并输出,前面输出标题 “The added matrix is:”
如果不能相加输出 “Can not add!”;
(3) 矩阵乘。如果两个矩阵可以相乘,进行两个矩阵乘并输出,前面输出标题 “The product matrix is:”
如果不能相乘输出 “Can not multiply!”
矩阵的输入:有多行,第1行包括三个整数,分别是矩阵的大小m,n及非零元素的个数r。后面r行分别输入各个非零元素的 行、列、值。
矩阵的输出:有两种形式,操作时分别用符号“L”、“H”指出输出形式。
L: 以三元组的形式输出,即先输出矩阵的行数、列数和非零元素个数,再依次输出各个非零元素的行、列和值。
H: 按人们习惯的矩阵格式输出,即输出一个m*n的矩阵,是零元素的输出0,非零元素输出元素值。设定每个元素占位宽度为4。(要输出行号和列号,并对齐)
例如:输入如下:

10 8 4   //第1个矩阵 10行,8列,4个非零元素
1 8 1    //第1行第8列元素值为1
3 3 2    //第3行第3列元素值为2
3 7 3    //第3行第7列元素值为3
10 1 4   //第10行第1列元素值为4
10 8 2   //第2个矩阵 10行,8列,2个非零元素
2 6 1    //第2行第6列元素值为1
3 7 -3    //第3行第7列元素值为-3
H   //输出格式类别

输出如下:

The transformed matrix  is:
        1   2   3   4   5   6   7   8   9  10
   1   0   0   0   0   0   0   0   0   0   4
   2   0   0   0   0   0   0   0   0   0   0
   3   0   0   2   0   0   0   0   0   0   0
   4   0   0   0   0   0   0   0   0   0   0
   5   0   0   0   0   0   0   0   0   0   0
   6   0   0   0   0   0   0   0   0   0   0
   7   0   0   3   0   0   0   0   0   0   0
   8   1   0   0   0   0   0   0   0   0   0
The added matrix is:
       1   2   3   4   5   6   7   8
   1   0   0   0   0   0   0   0   1
   2   0   0   0   0   0   1   0   0
   3   0   0   2   0   0   0   0   0
   4   0   0   0   0   0   0   0   0
   5   0   0   0   0   0   0   0   0
   6   0   0   0   0   0   0   0   0
   7   0   0   0   0   0   0   0   0
   8   0   0   0   0   0   0   0   0
   9   0   0   0   0   0   0   0   0
  10   4   0   0   0   0   0   0   0
Can not multiply!

再如,输入矩阵如下:

100 90 5     //矩阵的行数为100,列数为90,共5个非零元素。
1 10 100     //a(1,10)=100
50 60 200    //a(50,60)=200
50 80 100    //a(50,80)=100
60 60 200    //a(60,60)=200
99 89 10    //a(99,89)=10
100 90 4     //矩阵b的行数为100,列数为90,共4个非零元素。
1 1 10       //b(1,1)=10
50 60 -200    //b(50,60)=-200
50 80 100     //b(50,80)=100
70 70 10     //b(70,70)=10
L

输出如下:

The transformed matrix  is:
Rows=100,Cols=90,r=5
10 1 100
60 50 200
60 60 200
80 50 100
89 99 10
The added matrix is:
Rows=100,Cols=90,r=6
1 1 10
1 10 100
50 80 200
60 60 200
70 70 10
99 89 10
Can not multiply!

例如:
输入

100 90 5
1 10 100
50 60 200
50 80 100
60 60 200
99 89 10
100 90 4
1 1 10
50 60 -200
50 80 100
70 70 10
L

输出

The transformed matrix is:
Rows=90,Cols=100,r=5
10 1 100
60 50 200
60 60 200
80 50 100
89 99 10
The added matrix is:
Rows=100,Cols=90,r=6
1 1 10
1 10 100
50 80 200
60 60 200
70 70 10
99 89 10
Can not multiply!

稀疏矩阵的乘法搞了好久仍没搞出来,最后参考了把三元组转换为矩阵再相乘的方法才做出来(感觉并不是很符合要求)

#include<cstdio>
using namespace std;
typedef struct triple//顺序存储
{
    
    
    int row;
    int col;
    int val;
}element;
void Swap(element &a,element &b)//交换两个元素,用在排序中
{
    
    
    element t=a;
    a=b;
    b=t;
}
class matrix//矩阵类
{
    
    
private:
    element e[505];//矩阵元素
    int rows;//行,private型
    int cols;//列,private型
    int r;//元素个数,private型
    int m[505][505];
public:
    void create();//创建矩阵
    void trans(matrix a);//求矩阵的转置
    void add(matrix a,matrix b);//求两个矩阵相加
    void mul(matrix a,matrix b);//求两个矩阵相乘
    void show_l();//按习惯的矩阵格式输出
    void show_h();//按三元组的形式输出
    int getrows();//获取矩阵的行数
    int getcols();//获取矩阵的列数
    int getr();//获取矩阵的元素
    void transmatrix();
};
int matrix::getrows()
{
    
    
    return rows;
}
int matrix::getcols()
{
    
    
    return cols;
}
int matrix::getr()
{
    
    
    return r;
}
void matrix::create()
{
    
    
    scanf("%d %d %d",&rows,&cols,&r);
    for(int i=1;i<=r;i++)
    {
    
    
        scanf("%d %d %d",&e[i].row,&e[i].col,&e[i].val);
    }
}
void matrix::trans(matrix a)//求矩阵的转置
{
    
    
    rows=a.cols;
    cols=a.rows;
    r=a.r;
    for(int i=1;i<=r;i++)
    {
    
    
        e[i].col=a.e[i].row;
        e[i].row=a.e[i].col;
        e[i].val=a.e[i].val;
    }
    for(int i=1;i<=r-1;i++)//按行升序排序,行相同时按列升序排序
    {
    
    
        for(int j=i+1;j<=r;j++)
        {
    
    
            if(e[i].row>e[j].row)Swap(e[i],e[j]);
            else if(e[i].row==e[j].row)
            {
    
    
                if(e[i].col>e[j].col)Swap(e[i],e[j]);
            }
        }
    }
}
void matrix::add(matrix a,matrix b)//求两个矩阵相加
{
    
    
    rows=a.rows;
    cols=a.cols;
    int i=1,j=1,k=1;
    for(i=1;i<=a.r;i++)
    {
    
    
        for(j=1;j<=b.r;j++)
        {
    
    
            if(a.e[i].row==b.e[j].row&&a.e[i].col==b.e[j].col)//先找有无相等的元素位置
            {
    
    
                if(a.e[i].val+b.e[j].val!=0)//相加的和不为0的情况。此时表示找到
                {
    
    
                    e[k].row=a.e[i].row;
                    e[k].col=a.e[i].col;
                    e[k].val=a.e[i].val+b.e[j].val;
                    k++;
                }
                break;
            }
        }
        if(j==b.r+1)//没找到,说明没有与第i个元素位置相等的元素
        {
    
    
            e[k].row=a.e[i].row;
            e[k].col=a.e[i].col;
            e[k].val=a.e[i].val;
            k++;
        }
    }
    for(i=1;i<=b.r;i++)//找a,b矩阵中元素位置不同的元素
    {
    
    
        for(j=1;j<=a.r;j++)
        {
    
    
            if(a.e[j].row==b.e[i].row&&a.e[j].col==b.e[i].col)break;
        }
        if(j==a.r+1)
        {
    
    
            e[k].row=b.e[i].row;
            e[k].col=b.e[i].col;
            e[k].val=b.e[i].val;
            k++;
        }
    }
    r=k-1;//记录保留下来的元素个数
    for(i=1;i<=r-1;i++)//按行升序排序,行相同时按列升序排序
    {
    
    
        for(j=i+1;j<=r;j++)
        {
    
    
            if(e[i].row>e[j].row)Swap(e[i],e[j]);
            else if(e[i].row==e[j].row)
            {
    
    
                if(e[i].col>e[j].col)Swap(e[i],e[j]);
            }
        }
    }
}
void matrix::transmatrix()//转换成非稀疏矩阵
{
    
    
    for(int i=1;i<=rows;i++)
    {
    
    
        for(int j=1;j<=cols;j++)
        {
    
    
            m[i][j]=0;
        }
    }
    for(int i=1;i<=r;i++)
    {
    
    
        m[e[i].row][e[i].col]=e[i].val;
    }
}
void matrix::mul(matrix a,matrix b)//矩阵相乘
{
    
    
    rows=a.rows;
    cols=b.cols;
    for(int i=1;i<=a.r-1;i++)//按行升序排序,行相同时按列升序排序
    {
    
    
        for(int j=i+1;j<=a.r;j++)
        {
    
    
            if(a.e[i].row>a.e[j].row)Swap(a.e[i],a.e[j]);
            else if(a.e[i].row==a.e[j].row)
            {
    
    
                if(a.e[i].col>a.e[j].col)Swap(a.e[i],a.e[j]);
            }
        }
    }
    for(int i=1;i<=b.r-1;i++)//按列升序排序,列相同时按行升序排序
    {
    
    
        for(int j=i+1;j<=b.r;j++)
        {
    
    
            if(b.e[i].col>b.e[j].col)Swap(b.e[i],b.e[j]);
            else if(b.e[i].col==b.e[j].col)
            {
    
    
                if(b.e[i].row>b.e[j].row)Swap(b.e[i],b.e[j]);
            }
        }
    }
    int sum,t=1;
    a.transmatrix();
    b.transmatrix();
    for(int i=1;i<=a.rows;i++)//矩阵相乘
    {
    
    
        for(int j=1;j<=b.cols;j++)
        {
    
    
            sum=0;//求第i行第j列的所有非0元素和
            for(int k=1;k<=a.cols;k++)
            {
    
    
                sum+=a.m[i][k]*b.m[k][j];
            }
            if(sum!=0)
            {
    
    
                e[t].row=i;
                e[t].col=j;
                e[t].val=sum;
                t++;
            }
        }
    }
    r=t-1;//记录保留下来的元素个数
    for(int i=1;i<=r-1;i++)
    {
    
    
        for(int j=i+1;j<=r;j++)//按行升序排序,行相同时按列升序排序
        {
    
    
            if(e[i].row>e[j].row)Swap(e[i],e[j]);
            else if(e[i].row==e[j].row)
            {
    
    
                if(e[i].col>e[j].col)Swap(e[i],e[j]);
            }
        }
    }
}
void matrix::show_h()
{
    
    
    int i,j,k,zero=0;
    printf("    ");
    for(i=1;i<=cols;i++)
    {
    
    
        printf("%4d",i);
    }
    printf("\n");
    for(i=1;i<=rows;i++)
    {
    
    
        printf("%4d",i);
        for(j=1;j<=cols;j++)
        {
    
    
            for(k=1;k<=r;k++)
            {
    
    
                if(e[k].row==i&&e[k].col==j)//坐标(i,j)出现在所有非0元素中
                {
    
    
                    printf("%4d",e[k].val);
                    break;
                }
            }
            if(k==r+1)printf("%4d",zero);//没有出现,就输出0
        }
        printf("\n");
    }
}
void matrix::show_l()
{
    
    
    for(int i=1;i<=r;i++)
    {
    
    
        printf("%d %d %d\n",e[i].row,e[i].col,e[i].val);
    }
}
matrix m1,m2,mtrans,madd,mmul;
int main()
{
    
    
    char ss[5];
    m1.create();
    m2.create();
    mtrans.trans(m1);//转置
    madd.add(m1,m2);//相加
    mmul.mul(m1,m2);//相乘
    scanf("%s",ss);
    if(ss[0]=='H')
    {
    
    
        printf("The transformed matrix is:\n");
        mtrans.show_h();
        if(m1.getrows()==m2.getrows()&&m1.getcols()==m2.getcols())
        {
    
    
            printf("The added matrix is:\n");
            madd.show_h();
        }
        else printf("Can not add!\n");
        if(m1.getcols()==m2.getrows())
        {
    
    
            printf("The product matrix is:\n");
            mmul.show_h();
        }
        else printf("Can not multiply!\n");
    }
    else if(ss[0]=='L')
    {
    
    
        printf("The transformed matrix is:\n");
        printf("Rows=%d,Cols=%d,r=%d\n",mtrans.getrows(),mtrans.getcols(),mtrans.getr());
        mtrans.show_l();
        if(m1.getrows()==m2.getrows()&&m1.getcols()==m2.getcols())
        {
    
    
            printf("The added matrix is:\n");
            printf("Rows=%d,Cols=%d,r=%d\n",madd.getrows(),madd.getcols(),madd.getr());
            madd.show_l();
        }
        else printf("Can not add!\n");
        if(m1.getcols()==m2.getrows())
        {
    
    
            printf("The product matrix is:\n");
            printf("Rows=%d,Cols=%d,r=%d\n",mmul.getrows(),mmul.getcols(),mmul.getr());
            mmul.show_l();
        }
        else printf("Can not multiply!\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/upc122/article/details/105624905
今日推荐