稀疏矩阵的转置和乘法——数据结构课程

 

稀疏矩阵压缩了储存空间。但在进行运算的时候却没有原矩阵这样方便。

其中,data[0].row data[0].col 储存该矩阵的行和列。

另外,其实在三元数组储存的时候,该程序是默认输入的时候行优先的格式。否则就会出现这种不识别的情况,如果想兼容性强一点,就预先排个序。

 

在用三元组储存稀疏矩阵的时候,还需要维护:每一行第一个非零元素在三元组中的位置。储存这样的一个信息,就能在访问时,快速定位到到某一行的元素。

 

 

 

#include <iostream>  //教学用 2021.10
#include <iomanip>
#include <string.h>
#include <algorithm>
using namespace std;

const int MAXSIZE = 100; //定义非零元素的最多个数
const int MAXROW = 10; //定义数组行数的最大值
const int SIZENUM = 10;

typedef struct  //定义行序优先的顺序表
{
    typedef struct //定义三元组元素
    {
        int row, col; //矩阵的行号和列号
        int value; //矩阵元素值
    } term;
    term data[MAXSIZE+2]; //非0元三元组表
    int rpos[MAXROW+1];   //每行第一个非零元素在三元组data中的位置表
    
} RLSMatrix;
//如果输入的格式是行优先 则进行排序处理 
bool my_sort(RLSMatrix::term a,RLSMatrix::term b)
{return a.row<b.row;}

//输入三元组矩阵21
bool InputTSMatrix(RLSMatrix &M)
{
    cout << "输入矩阵的行数、列数和非零元素个数: ";
    cin >> M.data[0].row >> M.data[0].col >> M.data[0].value;
    cout << "请输入非零元素对应的行号、列号和相应的元素值: " << endl;
    for (int i = 1; i <= M.data[0].value; i++)
    {
        cin >> M.data[i].row >> M.data[i].col >> M.data[i].value;
    }
    return true;
}

//输出矩阵,按标准格式输出
bool OutputSMatrix(RLSMatrix M)
{
    int i, j, k = 1;
    for (i = 0; i < M.data[0].row; i++)
    {
        for (j = 0; j < M.data[0].col; j++)
        {
            if ((M.data[k].row-1) == i && (M.data[k].col-1) == j)
            {
                cout << setw(4) << M.data[k].value;
                k++;
            }
            else
                cout << setw(4) << "0";
        }//end_j
        cout << endl;
    }//end_i
    return true;
}

//稀疏矩阵的快速转置
int FastTranMat()   //ok
{
    RLSMatrix M, T;
    int num[MAXROW+1]; //表示矩阵M中第col列非零元素的个数
    int cpot[MAXROW+1]; //表示矩阵M中第col列第一个非0元素在b.data中的位置
    int p, q, col, t;
    InputTSMatrix(M); //输入稀疏矩阵   行列互换 
    T.data[0].row = M.data[0].col;
    T.data[0].col = M.data[0].row;
    T.data[0].value = M.data[0].value;//非零元素的数量 
    if (T.data[0].value)
    {
        for (col = 1; col <= M.data[0].col; col++) //M中各列元素个数初始化
            num[col] = 0;
        for (t = 1; t <= M.data[0].value; t++)
        {
            ++num[M.data[t].col ]; //求M中每一列非零元个数
        }
        
         //求第col列第一个非零元在b.data中的序号
        cpot[1] = 1;
        for (col = 2; col <= M.data[0].col; col++)//对每一列进行扫描 
        {
            cpot[col] = cpot[col-1] + num[col-1];//M中第col列第一个非0元素在b.data中的位置
        }
        for (p = 1; p <= M.data[0].value; p++)//由行优先储存到列优先储存的转换 
        {
            col = M.data[p].col; //稀疏矩阵M中每个元素对应的列号
            q = cpot[col]; //稀疏矩阵M中第一个非零元素位置
            T.data[q].row = M.data[p].col;
            T.data[q].col = M.data[p].row;
            T.data[q].value = M.data[p].value;
            ++cpot[col];
        }//end_for
    }//end_if
    cout << "运用快速算法,输入矩阵的转置为: " << endl;
    OutputSMatrix(T);
    return 1;
}
bool Count(RLSMatrix &M) //计算稀疏矩阵每一行非零元素个数
{
    int row, p;
    int num[MAXROW+1];
    //预处理
    sort(M.data,M.data+M.data[0].value,my_sort) ;
    
    for (row = 1; row <= M.data[0].row; row++)
    {
        num[row] = 0; //清零
    }
    for (p = 1; p <= M.data[0].value; p++)
    {
        ++num[M.data[p].row]; //统计M每一行非零元个数
    }
    M.rpos[1] = 1;
        //M中每一行非零元素的起始位置
    for (row = 2; row <= M.data[0].row; row++)
    {
        M.rpos[row] = M.rpos[row-1] + num[row-1];
    }
    return true;
}
bool MultSMatrix()//两个稀疏矩阵的乘法Q=M*N 
{
    RLSMatrix M, N, Q;  //构建三个带链接信息的三元组表示的数组
    InputTSMatrix(M);  //输入矩阵M的三元组数组
    InputTSMatrix(N);  //输入矩阵N的三元数组 
    Count(M); //计算矩阵M每行非零数的数量和位置 
    Count(N);//计算矩阵N 
    
    if (M.data[0].col != N.data[0].row)//能否进行矩阵乘法 
    {
        cout << "Error!";
        return false;
    }
    //Q的初始化,将结果储存在Q中 
    Q.data[0].row = M.data[0].row;
    Q.data[0].col = N.data[0].col;
    Q.data[0].value = 0;
    
    int mrow, nrow, p, q, t, tp, qcol;
    int ctemp[MAXROW+1]; //辅助数组, 
    //如果Q是非零矩阵
    if (M.data[0].value * N.data[0].value)
    {
        for (mrow = 1; mrow <= M.data[0].row; mrow++)
        {
                //当前行各元素累加器清零
            for (int x = 1; x <= N.data[0].col; x++)
            {
                ctemp[x] = 0;
            }//end_x
  //当前行的首个非零元素在三元组中的位置为此行前所有非0元素加1
            Q.rpos[mrow] = Q.data[0].value + 1;
            if (mrow < M.data[0].row)
            {
                tp = M.rpos[mrow+1];
            }
            else   //如果当前列为最后一列 
                tp = M.data[0].value + 1;
                
                
            for (p = M.rpos[mrow]; p < tp; p++) //对当前行的每个非零元素操作
            {
                nrow = M.data[p].col; //在N中找到与M操作元素的c值相等的行值r
                if (nrow < N.data[0].row)
                {
                    t = N.rpos[nrow+1];
                }
                else
                    t = N.data[0].value + 1;
                   //对找出的行的每个非零元素进行操作
                for (q = N.rpos[nrow]; q < t; q++)
                {
                    qcol = N.data[q].col;
                   //将乘得到的对应值放在相应元素的累加器里面
                    ctemp[qcol] += M.data[p].value * N.data[q].value;
                }
            }//p_end_for

//对已经求出的累加器中的值压缩到Q中
            for (qcol = 1; qcol <= Q.data[0].col; qcol++)
            {
                if (ctemp[qcol])
                {
                    if (++Q.data[0].value > MAXSIZE)
                    {
                        cout << "Error!" << endl;
                        return 0;
                    }
                    Q.data[Q.data[0].value].row = mrow;
                    Q.data[Q.data[0].value].col = qcol;
                    Q.data[Q.data[0].value].value = ctemp[qcol];
                }
            }//qcol_end_for
        }//arow_end_for
    }//end_if
    cout << "两个稀疏矩阵相乘的结果为:\n";
    OutputSMatrix(Q);
    return 1;
}
int main()
{
    char c;
    cout << "请选择要进行的操作";
    cout << setw(6) << '*' << " 1: 稀疏矩阵的快速转置算法" << endl;
    cout << setw(6) << '*' << " 2: 稀疏矩阵的乘法的快速算法" << endl;
    cout << setw(6) << '*' << " 0: 退出程序" << endl;
    cout.fill(' ');
    c = getchar();
    switch(c)
    {
        case '0':break;
        case '1':
            FastTranMat();//1: 稀疏矩阵的快速转置算法
            break;
        case '2':
            MultSMatrix();//2: 稀疏矩阵的乘法的快速算法 
            break;
        default:
            cout << "错误!无此操作" << endl << endl;
            break;
    }
    return 0;
}

 

posted @ 2021-10-27 15:20  浪矢-CL  阅读(200)  评论(0编辑  收藏  举报