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


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

    其中,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 << "两个稀疏矩阵相乘的结果为:
    ";
        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;
    }
  • 相关阅读:
    javaWeb服务详解【客户端调用】(含源代码,测试通过,注释) ——Emp实体类
    javaWeb服务详解【客户端调用】(含源代码,测试通过,注释) ——Dept实体类
    javaWeb服务详解【客户端调用】(含源代码,测试通过,注释) ——Dept实体类
    javaWeb服务详解(含源代码,测试通过,注释) ——web.xml
    hdu2044:一只小蜜蜂
    最大连续子序列和
    牛客练习赛20 F-填数字
    Attack City and Capture Territory & 取石子(博弈)
    畅通工程1
    和最大子序列
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/15470889.html
Copyright © 2020-2023  润新知