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;
    }

  • 相关阅读:
    去掉影响美观的横滚动条
    Visio绘制事件分解图
    Visio绘制系统图
    asp.net与js中字符串的HTML编码与解码
    《ERP从内部集成起步》读书笔记——第一章 Garthner公司是如何提出ERP的 1.1尊重历史
    Asp.net页面传参数给Silverlight
    Gridview中格式化数据的方法
    让silverlight不在最顶层,可以在悬浮层之下
    DateTime类型中 DayOfWeek时的英文如何转换成中文(转)
    Asp.net页面中通过Js控制Silverlight显示值
  • 原文地址:https://www.cnblogs.com/hjj-fighting/p/12742805.html
Copyright © 2011-2022 走看看