zoukankan      html  css  js  c++  java
  • 稀疏矩阵加减,乘除, 逆 (转)

    https://blog.csdn.net/u011478505/article/details/42747257

    #include <iostream>
    #include <iomanip>
    using namespace std;


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


    typedef struct                    //定义三元组元素
    {
        int r, c;                    //矩阵的行号和列号
        int v;                        //矩阵元素值
    }Triple;


    typedef struct                    //定义普通三元组对象
    {
        Triple data[MAXSIZE+1];        
        int rows, cols, nzeroNums;    //行数、列数、非零元素个数
    }TSMatrix;


    typedef struct                    //定义行逻辑链接的顺序表
    {
        Triple data[MAXSIZE+2];        //非0元三元组表
        int rpos[MAXROW+1];            //各行第一个非零元素的位置表
        int rows, cols, nzeroNums;    //行数、列数、非零元素个数
    }RLSMatrix;


    //输入三元组矩阵
    template <class T>
    bool InputTSMatrix(T &M, int y)        
    {
        cout << "输入矩阵的行数、列数和非零元素个数: ";
        cin >> M.rows >> M.cols >> M.nzeroNums;
        cout << "请输入非零元素对应的行号、列号和相应的元素值: " << endl;
        for (int i = 1; i <= M.nzeroNums; i++)
        {
            cin >> M.data[i].r >> M.data[i].c >> M.data[i].v;
        }
        return true;
    }


    //输出矩阵,按标准格式输出
    template <class T>
    bool OutputSMatrix(T M)
    {
        int i, j, k = 1;
        for (i = 0; i < M.rows; i++)
        {
            for (j = 0; j < M.cols; j++)
            {
                if ((M.data[k].r-1) == i && (M.data[k].c-1) == j)
                {
                    cout << setw(4) << M.data[k].v;
                    k++;
                }
                else
                    cout << setw(4) << "0";
            }//end_j
            cout << endl;
        }//end_i
        return true;
    }


    //求稀疏矩阵的转置
    int TranSMatrix()
    {
        TSMatrix M, T;
        InputTSMatrix(M, 0);
        int col, p, q = 1;
        T.rows = M.cols;
        T.cols = M.rows;
        T.nzeroNums = M.nzeroNums;
        if (T.nzeroNums)
        {
            for (col = 1; col <= M.cols; col++)
            {
                for (p = 1; p <= M.nzeroNums; p++)
                {
                    if (M.data[p].c == col)
                    {
                        T.data[q].r = M.data[p].c;
                        T.data[q].c = M.data[p].r;
                        T.data[q].v = M.data[p].v;
                        ++q;
                    }
                }//end_p
            }//end_col
        }//end_if
        cout << "运用普通转置算法, 输入矩阵的转置矩阵为: " << endl;
        OutputSMatrix(T);
        return 1;
    }


    //稀疏矩阵的快速转置
    int FastTranMat()
    {
        TSMatrix M, T;
        int num[MAXROW+1];        //表示矩阵M中第col列非零元素的个数
        int cpot[MAXROW+1];        //表示矩阵M中第col列第一个非0元素在b.data中的位置
        int p, q, col, t;
        InputTSMatrix(M, 0);        //输入稀疏矩阵
        T.rows = M.cols;
        T.cols = M.rows;
        T.nzeroNums = M.nzeroNums;
        if (T.nzeroNums)
        {
            for (col = 1; col <= M.cols; col++)//M中各列元素初始化
            {
                num[col] = 0;
            }
            for (t = 1; t <= M.nzeroNums; t++)
            {
                ++num[M.data[t].c];            //求M中每一列非零元个数
            }
            //求第col列第一个非零元在b.data中的序号
            cpot[1] = 1;
            for (col = 2; col <= M.cols; col++)
            {
                cpot[col] = cpot[col-1] + num[col-1];
            }
            for (p = 1; p <= M.nzeroNums; p++)
            {
                col = M.data[p].c;            //稀疏矩阵M中每个元素对应的列号
                q = cpot[col];                //稀疏矩阵M中第一个非零元素位置
                T.data[q].r = M.data[p].c;
                T.data[q].c = M.data[p].r;
                T.data[q].v = M.data[p].v;
                ++cpot[col];
            }//end_for
        }//end_if
        cout << "运用快速算法,输入矩阵的转置为: " << endl;
        OutputSMatrix(T);
        return 1;
    }


    //求取稀疏矩阵每一行非零元个数
    bool Count(RLSMatrix &M)
    {
        int row, p;
        int num[MAXROW+1];
        for (row = 1; row <= M.rows; row++)
        {
            num[row] = 0;                //清零
        }
        for (p = 1; p <= M.nzeroNums; p++)
        {
            ++num[M.data[p].r];            //统计M每一行非零元个数
        }
        M.rpos[1] = 1;
        //M中每一行非零元的起始位置
        for (row = 2; row <= M.rows; row++)
        {
            M.rpos[row] = M.rpos[row-1] + num[row-1];
        }
        return true;
    }


    //两个稀疏矩阵的乘法
    bool MultSMatrix()
    {
        RLSMatrix M, N, Q;            //构建三个带链接信息的三元组表示的数组
        InputTSMatrix(M, 1);        //用普通三元组形式输入数组
        InputTSMatrix(N, 1);
        Count(M);
        Count(N);
        if (M.cols != N.rows)
        {
            cout << "Error!";
            return false;
        }
        //Q的初始化
        Q.rows = M.rows;
        Q.cols = N.cols;
        Q.nzeroNums = 0;
        int mrow, nrow, p, q, t, tp, qcol;
        int ctemp[MAXROW+1];            //辅助数组
        //如果Q是非零矩阵
        if (M.nzeroNums * N.nzeroNums)
        {
            for (mrow = 1; mrow <= M.rows; mrow++)
            {
                //当前行各元素累加器清零
                for (int x = 1; x <= N.cols; x++)
                {
                    ctemp[x] = 0;
                }//end_x
                //当前行的首个非零元素在三元组中的位置为此行前所有非0元素加1
                Q.rpos[mrow] = Q.nzeroNums + 1;
                if (mrow < M.rows)
                {
                    tp = M.rpos[mrow+1];
                }
                else
                    tp = M.nzeroNums + 1;
                for (p = M.rpos[mrow]; p < tp; p++)        //对当前行的每个非零元素操作
                {
                    nrow = M.data[p].c;        //在N中找到与M操作元素的c值相等的行值r
                    if (nrow < N.rows)
                    {
                        t = N.rpos[nrow+1];
                    }
                    else
                        t = N.nzeroNums + 1;
                    //对找出的行的每个非零元素进行操作
                    for (q = N.rpos[nrow]; q < t; q++)
                    {
                        qcol = N.data[q].c;
                        //将乘得到的对应值放在相应元素的累加器里面
                        ctemp[qcol] += M.data[p].v * N.data[q].v;
                    }
                }//p_end_for
                
                //对已经求出的累加器中的值压缩到Q中
                for (qcol = 1; qcol <= Q.cols; qcol++)
                {
                    if (ctemp[qcol])
                    {
                        if (++Q.nzeroNums > MAXSIZE)
                        {
                            cout << "Error!" << endl;
                            return 0;
                        }
                        Q.data[Q.nzeroNums].r = mrow;
                        Q.data[Q.nzeroNums].c = qcol;
                        Q.data[Q.nzeroNums].v = ctemp[qcol];
                    }
                }//qcol_end_for
            }//arow_end_for
        }//end_if
        cout << "两个稀疏矩阵相乘的结果为: ";
        OutputSMatrix(Q);
        return 1;
    }


    //两个稀疏矩阵的加法
    int AddMatrix()
    {
        TSMatrix A, B, C;
        int i = 1, j = 1, k = 1;    //i, j, k分别用以保存A、B、C非零元素个数
        int value = 0;
        InputTSMatrix(A, 0);
        InputTSMatrix(B, 0);
        if (A.rows != B.rows || A.cols != B.cols)
        {
            cout << "两个稀疏矩阵的大小不等,不能相加!" << endl;
            return 0;
        }
        if (A.rows == B.rows && A.cols == B.cols)
        {
            while (i <= A.nzeroNums && j <= B.nzeroNums)
            {
                if (A.data[i].r == B.data[j].r)
                {
                    if (A.data[i].c < B.data[j].c)
                    {
                        C.data[k].r = A.data[i].r;
                        C.data[k].c = A.data[i].c;
                        C.data[k].v = A.data[i].v;
                        k++;
                        i++;
                    }
                    else if (A.data[i].c > B.data[j].c)
                    {
                        C.data[k].r = B.data[j].r;
                        C.data[k].c = B.data[j].c;
                        C.data[k].v = B.data[j].v;
                        k++;
                        j++;
                    } 
                    else
                    {
                        value = A.data[i].v + B.data[j].v;
                        if (value != 0)
                        {
                            C.data[k].r = A.data[i].r; 
                            C.data[k].c = A.data[i].c; 
                            C.data[k].v = value;
                            k++;
                        }
                        i++;
                        j++;
                    }
                }//end_if
                else if (A.data[i].r < B.data[j].r)
                {
                    C.data[k].r = A.data[i].r;
                    C.data[k].c = A.data[i].c;
                    C.data[k].v = A.data[i].v;
                    k++;
                    i++;
                } 
                else
                {
                    C.data[k].r = B.data[j].r;
                    C.data[k].c = B.data[j].c;
                    C.data[k].v = B.data[j].v;
                    k++;
                    j++;
                }
                //把剩余部分元素存入C中
                if (i > A.nzeroNums && j <= B.nzeroNums)
                {
                    for (; j <= B.nzeroNums; j++)
                    {
                        C.data[k].r = B.data[j].r;
                        C.data[k].c = B.data[j].c;
                        C.data[k].v = B.data[j].v;
                        k++;
                    }
                }
                if (i <= A.nzeroNums && j > B.nzeroNums)
                {
                    for (; i <= A.nzeroNums; i++)
                    {
                        C.data[k].r = A.data[i].r;
                        C.data[k].c = A.data[i].c;
                        C.data[k].v = A.data[i].v;
                        k++;
                    }
                }
            }//end_while
            C.rows = A.rows;
            C.cols = A.cols;
            C.nzeroNums = k-1;
            cout << "输出两个稀疏矩阵的和: " << endl;
            OutputSMatrix(C);
            return 1;
        }//end_if
        else
            return 0;
    }


    //两个稀疏矩阵的减法
    int SubMatrix()
    {
        TSMatrix A, B, C;
        int m = 1, n = 1, k = 1, temp;  
        InputTSMatrix(A, 0);
        InputTSMatrix(B, 0);
        C.rows = A.rows;
        C.cols = A.cols;
        C.nzeroNums = 0;
        if (A.rows == B.rows && A.cols == B.cols)
        {
            while (m <= A.nzeroNums && n <= B.nzeroNums)
            {
                if (A.data[m].r == B.data[n].r)
                {
                    if (A.data[m].c == B.data[n].c)
                    {
                        temp = A.data[m].v - B.data[n].v;
                        if (temp != 0)
                        {
                            C.data[k].r = A.data[m].r;
                            C.data[k].c = A.data[m].c;
                            C.data[k].v = temp;
                            k++;
                        }
                        m++;
                        n++;
                    }
                    else if (A.data[m].c < B.data[n].c)
                    {
                        C.data[k].r = A.data[m].r;
                        C.data[k].c = A.data[m].c;
                        C.data[k].v = A.data[m].v;
                        k++;
                        m++;
                    } 
                    else
                    {
                        C.data[k].r = B.data[n].r;
                        C.data[k].c = B.data[n].c;
                        C.data[k].v = -B.data[n].v;
                        k++;
                        n++;
                    }
                }
                else if (A.data[m].r < B.data[n].r)
                {
                    C.data[k].r = A.data[m].r;
                    C.data[k].c = A.data[m].c;;
                    C.data[k].v = A.data[m].v;
                    k++;
                    m++;
                } 
                else
                {
                    C.data[k].r = B.data[n].r;
                    C.data[k].c = B.data[n].c;
                    C.data[k].v = -B.data[n].v;
                    k++;
                    n++;
                }
            }//end_while
            if (m <= A.nzeroNums)
            {
                for (; m <= A.nzeroNums; m++)
                {
                    C.data[k].r = A.data[m].r;
                    C.data[k].c = A.data[m].c;
                    C.data[k].v = A.data[m].v;
                    k++;
                }
            }
            if (n <= B.nzeroNums)
            {
                for (; n <= B.nzeroNums; n++)
                {
                    C.data[k].r = B.data[n].r;
                    C.data[k].c = B.data[n].c;
                    C.data[k].v = -B.data[n].v;
                    k++;
                }
            }
            C.nzeroNums = k-1;
            cout << "两个稀疏矩阵的差为: ";
            OutputSMatrix(C);
            return 1;
        } //end_if
        else
        {
            cout << "两个稀疏矩阵的大小不同,不能相减! ";
            return 0;
        }
    }


    //得到矩阵元素M[i][j]的值
    int value(TSMatrix M, int i, int j)
    {
        int k;
        for (k = 1; k <= M.nzeroNums; k++)
        {
            if (M.data[k].r == i && M.data[k].c == j)
            {
                return M.data[k].v;
            }
        }
        return 0;
    }


    //矩阵乘法的算法2
    int MultMat()
    {
        TSMatrix A, B, C;
        InputTSMatrix(A, 0);
        InputTSMatrix(B, 0);
        int i, j, k, temp = 0, p = 1;
        if (A.cols != B.rows)
        {
            cout << "矩阵A的列数不等于矩阵B的行数不能相乘! ";
            return 0;
        }
        else
        {
            for (i = 1; i <= A.rows; i++)
            {
                for (j = 1; j <= B.cols; j++)
                {
                    temp = 0;
                    for (k = 1; k <= A.cols; k++)
                    {
                        temp += value(A, i, k) * value(B, k, j);
                    }
                    if (temp != 0)
                    {
                        C.data[p].r = i;
                        C.data[p].c = j;
                        C.data[p].v = temp;
                        p++;
                    }
                }
            }
            C.rows = A.rows;
            C.cols = B.cols;
            C.nzeroNums = p-1;
            OutputSMatrix(C);
            return 1;
        }
    }


    //计算矩阵的行列式, 通过递归算法来实现
    int JsMatrix(int s[][MAXROW], int n)
    {
        int i, j, k, r, total = 0;
        int b[SIZENUM][SIZENUM];    //b[N][N]用于存放在矩阵s[N][N]中元素s[0]的余之式
        
        if (n == 1)
        {
            total = s[0][0];
        }
        else if (n == 2)
        {
            total = s[0][0] * s[1][1] - s[0][1] * s[1][0];
        } 
        else
        {
            for (i = 0; i < n; i++)
            {
                for (j = 0; j < n-1; j++)
                {
                    for (k = 0; k < n-1; k++)
                    {
                        if (k >= i)
                        {
                            b[j][k] = s[j+1][k+1];
                        }
                        else
                        {
                            b[j][k] = s[j+1][k];
                        }    
                    }//end_for_k
                }//end_for_j
                if (i % 2 == 0)
                {
                    r = s[0][i] * JsMatrix(b, n-1);        //递归调用
                }
                else
                {
                    r = (-1) * s[0][i] * JsMatrix(b, n-1);
                }
                total += r;
            }//end_for_i
        }//end_else
        return total;
    }


    //求原矩阵个元素对应的余之式, 存放在b[n][n]中,定义为float型
    void N1Matrix(int s[][SIZENUM], float b[][SIZENUM], int n)
    {
        int i, j, k, l, m, g, a[SIZENUM][SIZENUM];
        for (i = 0; i < n; i++)
        {
            m = i;
            for (j = 0; j < n; j++)
            {
                g = j;
                for (k = 0; k < n-1; k++)
                {
                    for (l = 0; l < n-1; l++)
                    {
                        if (k >= m && l >= g)
                        {
                            a[k][l] = s[k+1][l+1];
                        }
                        else if (k < m && l >= g)
                        {
                            a[k][l] = s[k][l+1];
                        }
                        else if (k >= m && l < g)
                        {
                            a[k][l] = s[k+1][l];
                        }
                        else
                        {
                            a[k][l] = s[k][l];
                        }
                    }//end_for_l
                }//end_for_k
                b[i][j] = JsMatrix(a, n-1);
            }//end_for_j
        }//end_for_i
    }


    //稀疏矩阵求逆
    void InverseMat()
    {
        TSMatrix M;
        InputTSMatrix(M, 0);
        int i, j, k, n = M.rows;
        float temp;
        int a[SIZENUM][SIZENUM];
        float b[SIZENUM][SIZENUM], c[SIZENUM][SIZENUM];
        for (i = 0; i < n; i++)        //初始化矩阵a
        {
            for (j = 0; j < n; j++)
            {
                a[i][j] = 0;
            }
        }
        for (i = 1; i <= M.nzeroNums; i++)        //给矩阵a赋值
        {
            a[M.data[i].r-1][M.data[i].c-1] = M.data[i].v; 
        }
        cout << "稀疏矩阵对应的普通矩阵为: ";
        for (i = 0; i < n; i++)            //打印原矩阵
        {
            for (j = 0; j < n; j++)
            {
                cout << setw(4) << a[i][j] << setw(4);
            }
            cout << endl;
        }
        k = JsMatrix(a, n);
        cout << "矩阵的行列式值: |A| = " << k << endl;
        if (k == 0)
        {
            cout << "行列式的值为0, 原矩阵无逆矩阵!" << endl;
        }
        else
        {
            N1Matrix(a, b, n);    //调用函数,得到原矩阵各元素对应的余之式存放在数组b[n][n]中
            //求代数余之式
            cout << "普通矩阵各元素对应的代数余之式矩阵为: ";
            for (i = 0; i < n; i++)                
            {
                for (j = 0; j < n; j++)
                {
                    if ((i+j)%2 != 0 && b[i][j] != 0)
                    {
                        b[i][j] = -b[i][j];
                    }
                    cout << setw(4) << b[i][j] << setw(4);
                }
                cout << endl;
            }//end_for_i


            //对b[N][N]转置,此时b[n][n]存放的为原矩阵的伴随矩阵
            for (i = 0; i < n; i++)        
            {
                for (j = i+1; j < n; j++)
                {
                    temp = b[i][j];
                    b[i][j] = b[j][i];
                    b[j][i] = temp;
                }
            }
            cout << "伴随矩阵A*: " << endl;
            for (i = 0; i < n; i++)            //打印伴随矩阵A*
            {
                for (j = 0; j < n; j++)
                {
                    cout << setw(4) << b[i][j] << setw(4);
                }
                cout << endl;
            }
            for (i = 0; i < n; i++)            //求逆矩阵,此时c[n][n]中存放的是原矩阵的逆矩阵
            {
                for (j = 0; j < n; j++)
                {
                    c[i][j] = b[i][j]/k;
                }
            }
            cout << "逆矩阵(A*)/|A|: " << endl;
            for (i = 0; i < n; i++)            //打印逆矩阵
            {
                for (j = 0; j < n; j++)
                {
                    cout << setw(6) << c[i][j] << setw(6);
                }
                cout << endl;
            }
        }//end_else
    }


    int main()
    {
        char c;
        cout << setw(50) << "******欢迎使用稀疏矩阵的相关操作!******" << endl << endl;
        cout.fill('*');
        cout << setw(20) << '*';
        cout << "请选择要进行的操作";
        cout << setw(20) << '*' << endl;
        cout << setw(6) << '*' << " 1: 稀疏矩阵的普通转置算法" << endl;
        cout << setw(6) << '*' << " 2: 稀疏矩阵的快速转置算法" << endl;
        cout << setw(6) << '*' << " 3: 稀疏矩阵的乘法的快速算法" << endl;
        cout << setw(6) << '*' << " 4: 稀疏矩阵的乘法的经典算法" << endl;
        cout << setw(6) << '*' << " 5: 稀疏矩阵的加法" << endl;
        cout << setw(6) << '*' << " 6: 稀疏矩阵的减法" << endl;
        cout << setw(6) << '*' << " 7: 求稀疏矩阵的逆" << endl;
        cout << setw(6) << '*' << " 0: 退出程序" << endl;
        cout.fill(' ');
        c = getchar();
        switch(c)
        {
        case '1':
            TranSMatrix();
            break;
        case '2':
            FastTranMat();
            break;
        case '3':
            MultSMatrix();
            break;
        case '4':
            MultMat();
            break;
        case '5':
            AddMatrix();
            break;
        case '6':
            SubMatrix();
            break;
        case '7':
            InverseMat();
            break;
        case '0':
            cout << "谢谢使用! 再见!" << endl;
            break;
        default:
            cout << "错误命令!" << endl << endl;
            break;
        }
        return 0;
    }

  • 相关阅读:
    haproxy 2.5 发布
    cube.js sql 支持简单说明
    基于graalvm 开发一个cube.js jdbc driver 的思路
    apache kyuubi Frontend 支持mysql 协议
    oceanbase 资源池删除说明
    基于obd 的oceanbase 扩容说明
    jfilter一个方便的spring rest 响应过滤扩展
    cube.js schema 定义多datasource 说明
    typescript 编写自定义定义文件
    meow 辅助开发cli 应用的工具
  • 原文地址:https://www.cnblogs.com/hjj-fighting/p/12742805.html
Copyright © 2011-2022 走看看