稀疏矩阵加减,乘除, 逆 (转)

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

原文地址:https://www.cnblogs.com/hjj-fighting/p/12742805.html