zoukankan      html  css  js  c++  java
  • 稀疏矩阵的抽象数据类型和一些基本操作的实现

    头文件:

    #ifndef ADT_TSMatrix_H
    #define ADT_TSMatrix_H
    #define TRUE 1
    #define FALSE 0
    #define OK 1
    #define ERROR 0
    #define INFEASIBLE -1
    #define MYOVERFLOW -2
    #define MAXSIZE 12500 //假设非零元素个数的最大值为12500
    typedef int Status;
    typedef int Elemtype;//用指定标识符Elemtype代表int类型,顾名思义表示元素类型为int型
    
    typedef struct{
        int i, j;        //该非零元素的行下标和列下标
        Elemtype e;
    }Triple;
    
    typedef struct{
        Triple data[MAXSIZE + 1];//非零元三元组表,data[0]未用
        int mu, nu, tu;          //矩阵的行数,列数和非零元个数
    }TSMatrix;
    
    //-------------稀疏矩阵的基本操作------------
    
    Status CreateSMatrix(TSMatrix &M);//操作结果:创建稀疏矩阵M。
    
    Status DestroySMatrix(TSMatrix &M);//在稀疏矩阵存在的情况下,销毁稀疏矩阵M
    
    Status PrintSMatrix(TSMatrix M);//稀疏矩阵存在的情况下,输出稀疏矩阵M
    
    Status CopySMatrix(TSMatrix M, TSMatrix &T);//稀疏矩阵M存在,由稀疏矩阵M复制得到T
    
    Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q);
    //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M+N。
    
    Status SubtMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q);
    //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M-N。
    
    Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q);
    //稀疏矩阵M的列数等于N的行数,求得稀疏矩阵Q=M*N
    
    Status TransposeSMatrix(TSMatrix M, TSMatrix &T);
    //稀疏矩阵M存在,求得稀疏矩阵M的转置矩阵T
    
    Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T);
    //稀疏矩阵M存在,求得稀疏矩阵M的装置矩阵T,但这是一种效率更高的转置算法
    
    #endif

    上述操作的实现:

    #include"stdafx.h"
    //-------------稀疏矩阵的基本操作------------
    
    Status CreateSMatrix(TSMatrix &M)//操作结果:创建稀疏矩阵M。
    {
        cout << "please input the number of the row:";
        cin >> M.mu;
        cout << "please input the number of the column:";
        cin >> M.nu;
        cout << "please input the number of the elem which is not equal to zero:";
        cin >> M.tu;       //输入稀疏矩阵的行数、列数、非零元素数
        cout << "please input the data :" << endl;//输入矩阵的元素,一次输入行的位置,列的位置和元素的值
        for (int i1 = 1; i1 <= M.tu; ++i1){
            cin >> M.data[i1].i >> M.data[i1].j >> M.data[i1].e;
        }
        return OK;
    }
    
    Status DestroySMatrix(TSMatrix &M)//在稀疏矩阵存在的情况下,销毁稀疏矩阵M
    {
        if (M.tu != 0){
            for (int ii = 1; ii <= M.tu; ++ii){
                M.data[ii].i = 0;
                M.data[ii].j = 0;
                M.data[ii].e = 0;
            }
            M.mu = 0;
            M.tu = 0;
            M.nu = 0;
            return OK;
        }
        else return ERROR;
    }
    
    Status PrintSMatrix(TSMatrix M)//稀疏矩阵存在的情况下,输出稀疏矩阵M
    {
        if (M.tu == 0)return ERROR;
        else {
            cout << 'i' << "  " << "j" << "  " << "e" << endl;
            for (int ii = 1; ii <= M.tu; ++ii){
                cout << M.data[ii].i << " " << M.data[ii].j << " " << M.data[ii].e << endl;
            }
            cout << endl;
        }
        return OK;
    }
    
    Status CopySMatrix(TSMatrix M, TSMatrix &T)//稀疏矩阵M存在,由稀疏矩阵M复制得到T
    {
        T.mu = M.mu;
        T.nu = M.nu;
        T.tu = M.tu;
        for (int ii = 1; ii <= M.tu; ++ii){
            T.data[ii].i = M.data[ii].i;
            T.data[ii].j = M.data[ii].j;
            T.data[ii].e = M.data[ii].e;
        }
        return OK;
    }
    
    Status AddSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q)
    //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M+N。
    {
        if (M.mu == N.mu&&M.nu == N.nu){//稀疏矩阵M和N的行数列数相等,才进行运算
            Q.mu = M.mu;                //为Q的行和列赋值
            Q.nu = M.nu;
            int M_temp = 1, N_temp = 1; //这是M和N当前的位置都为1
            int len = 1;                //这是Q的当前非零元个数
            for (; M_temp<=M.tu&&N_temp<=N.tu; ++len){ 
                if (M.data[M_temp].i < N.data[N_temp].i){//如果M的当前非零元素的行值小于N的,则直接把M的这个元素拷贝给Q
                    Q.data[len].i = M.data[M_temp].i;
                    Q.data[len].j = M.data[M_temp].j;
                    Q.data[len].e = M.data[M_temp].e;    //M的当前位置向前走一步
                    ++M_temp;
                }
                else if (M.data[M_temp].i == N.data[N_temp].i){//如果M的当前非零元素的行值等于N的,则还需比较列值
                    if (M.data[M_temp].j < N.data[N_temp].j){  //如果M的列值<N的列值,这把M的这个元素拷贝给Q
                        Q.data[len].i = M.data[M_temp].i;
                        Q.data[len].j = M.data[M_temp].j;
                        Q.data[len].e = M.data[M_temp].e;
                        ++M_temp;                            //M的当前位置向前走一步
                    }
                    else if (M.data[M_temp].j == N.data[N_temp].j){//如果M的列值=N的列值
                        if (M.data[M_temp].e != -N.data[N_temp].e){//如果这个位置相同的两个元素之和不为零,则将相应的e值拷贝给Q
                            Q.data[len].i = M.data[M_temp].i;
                            Q.data[len].j = M.data[M_temp].j;
                            Q.data[len].e = M.data[M_temp].e + N.data[N_temp].e;
                        }
                        else --len;                               //如果和=0,则在这个循环中,Q的长度并未增加,将len减去1
                        ++N_temp;                                  //N的当前位置向前走一步
                        ++M_temp;                                  //M的当前位置向前走一步
                    }
                    else{                                         //如果M的列值>N的列值,把N的这个元素拷贝给Q
                        Q.data[len].i = N.data[N_temp].i;
                        Q.data[len].j = N.data[N_temp].j;
                        Q.data[len].e = N.data[N_temp].e;
                        ++N_temp;                                 //N的当前位置向前走一步
                    }
                }
                else{                                             //如果M的行值>N的行值,把N的这个元素拷贝给Q
                    Q.data[len].i = N.data[N_temp].i;
                    Q.data[len].j = N.data[N_temp].j;
                    Q.data[len].e = N.data[N_temp].e;
                    ++N_temp;                                     //N的当前位置向前走一步
                }
            }
            if (M_temp > M.tu){                                //如果是M的元素先检查完,则把N的剩下的元素拷贝给Q
                for (; N_temp <= N.tu; ++N_temp, ++len){
                    Q.data[len].i = N.data[M_temp].i;
                    Q.data[len].j = N.data[M_temp].j;
                    Q.data[len].e = N.data[M_temp].e;
                }
            }
            else{
                for (; M_temp <= M.tu; ++M_temp,++len){       //如果是N的元素先检查完,则把M的剩下的元素拷贝给Q
                    Q.data[len].i = M.data[M_temp].i;
                    Q.data[len].j = M.data[M_temp].j;
                    Q.data[len].e = M.data[M_temp].e;
                }
            }                                                //同时检查完,则不需要其他操作
                Q.tu = --len;
                return OK;
        }
        return ERROR;
    }
    
    
    Status SubtMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q)
    //稀疏矩阵M与N的行数和列数对应相等,求得稀疏矩阵Q=M-N。
    {
        for (int i = 1; i <= N.tu; ++i)         //减法只是加法的另一种形式而已,将矩阵N的全部数据元素取反,
            N.data[i].e = -N.data[i].e;         //然后按照加法的规则,进行运算
        if(AddSMatrix(M, N, Q))return OK;
        else return ERROR;
    }
    
    Status MultSMatrix(TSMatrix M, TSMatrix N, TSMatrix &Q)
    //稀疏矩阵M的列数等于N的行数,求得稀疏矩阵Q=M*N
    {
        if (M.nu != N.mu)return ERROR;           //如果M的列数和N的行数不相等,则矩阵无法相乘
        Q.mu = M.mu;
        Q.nu = N.nu;
        Q.tu = 0;
        int M_rpos[50] = { 0 }, N_rpos[50] = { 0 }, M_num[50] = { 0 }, N_num[50] = { 0 }, ctemp[50];
        M_rpos[1] = 1; N_rpos[1] = 1;            //M和N的第一行的第一个非零元素的位置一定是1
        for (int i = 1; i <= M.tu; ++i)          //求得M中每一行元素的个数
            ++M_num[M.data[i].i];
        for (int i = 1; i <= N.tu; ++i)          //求得N中每一行元素的个数
            ++N_num[N.data[i].i];
        for (int i = 2; i <= M.mu; ++i)          //求得M中每一行第一个非零元素的位置
            M_rpos[i] = M_rpos[i - 1] + M_num[i-1];
        for (int i = 2; i <= N.mu; ++i)          //求得N中每一行第一个非零元素的位置
            N_rpos[i] = N_rpos[i - 1] + N_num[i - 1];
        if (M.tu*N.tu != 0){                     //如果M和N中都有非零元素才进行下面的步骤
            for (int row = 1; row <= M.mu; ++row){//按照M中的行序对Q的结果进行求值
                for (int i = 1; i < 50; ++i)     //每次循环都要将这个临时累加器清零
                    ctemp[i] = 0;
                int tp = 0, t = 0, ccol = 0, brow = 0;
                if (row < M.mu)tp = M_rpos[row + 1];//如果行数<M的最大行数,则每行的下一行第一个非零元素的位置为M_rpos[row+1]
                else tp = M.tu + 1;                 //最后一行的为M.tu+1
                for (int p = M_rpos[row]; p < tp; ++p){//当前行的第一个元素的位置赋予P
                    brow = M.data[p].j;                //得到该元素的列数,从而对N相等的行进行运算
                    if (brow < N.mu)t = N_rpos[brow + 1];//如果行数<N的最大行数,则每行的下一行第一个非零元素的位置为N_rpos[row+1]
                    else t = N.tu + 1;                   //最后一行的为N.tu+1
                    for (int q = N_rpos[brow]; q < t; ++q){
                         ccol = N.data[q].j;                    //将该列的结果暂时保存在ctemp[ccol]中,因为
                        ctemp[ccol] += M.data[p].e*N.data[q].e; // 只有当该行全部运算完,才知道Q的该行的第ccol列确切的值
                    }
                }
                for (ccol = 1; ccol <= Q.nu;++ccol)//将结果赋予Q
                if (ctemp[ccol]){
                    Q.data[++Q.tu].i = row;
                    Q.data[Q.tu].j = ccol;
                    Q.data[Q.tu].e = ctemp[ccol];
                }
            }
        }
        return OK;
    }
    
    Status TransposeSMatrix(TSMatrix M, TSMatrix &T)
    //稀疏矩阵M存在,求得稀疏矩阵M的转置矩阵T
    {
        if (M.tu > 0){
            T.mu = M.nu;
            T.nu = M.mu;
            T.tu = 1;
            for (int i = 1; i <= M.nu; ++i){
                for (int j = 1; j <= M.tu; ++j){
                    if (M.data[j].j == i){
                        T.data[T.tu].i = M.data[j].j;
                        T.data[T.tu].j = M.data[j].i;
                        T.data[T.tu].e = M.data[j].e;
                        ++T.tu;
                    }
                }    
            }
            --T.tu;
            return OK;
        }
        return ERROR;
    }
    
    Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T)
    //稀疏矩阵M存在,求得稀疏矩阵M的装置矩阵T,但这是一种效率更高的转置算法
    {
        T.mu = M.nu;
        T.nu = M.mu;
        T.tu = M.tu;
        if (M.tu){
            int num[50] = { 0 };
            int cpot[50] = { 0 };
            cpot[1] = 1;
            for (int i = 1; i <= M.tu; ++i)
                ++num[M.data[i].j];
            for (int i = 2; i <= M.nu; ++i)
                cpot[i] = cpot[i - 1] + num[i - 1];
            for (int i = 1; i <= M.tu; ++i){
                int column = M.data[i].j;
                int pos = cpot[column];
                T.data[pos].i = M.data[i].j;
                T.data[pos].j = M.data[i].i;
                T.data[pos].e = M.data[i].e;
                ++cpot[column];
            }
        }
        return OK;
    }

    对于两种转置算法和矩阵加法的验证,主函数:

    // TSMatrix.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    int _tmain(int argc, _TCHAR* argv[])
    {
        TSMatrix M, T,Q,t;
        CreateSMatrix(M);
        TransposeSMatrix(M, T);
        FastTransposeSMatrix(M, t);
        PrintSMatrix(T);
        PrintSMatrix(t);
        AddSMatrix(M, T, Q);
        PrintSMatrix(Q);
        return 0;
    }

    结果:

    对于稀疏矩阵乘法的验证,主函数:

    // TSMatrix.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    int _tmain(int argc, _TCHAR* argv[])
    {
        TSMatrix M, T, Q;
        CreateSMatrix(M);
        CreateSMatrix(T);
        MultSMatrix(M, T, Q);
        PrintSMatrix(Q);
        return 0;
    }

    结果:

  • 相关阅读:
    asp.net 使用urlrewrite之后的form postback
    WebService来获取Context.User.Identity.Name为空的问题?
    求救:C#的一个绘图问题
    flex 使用webservice的域访问问题
    请教大家一个问题,有关于数据库的设计
    C# 中使用结构体
    Discuz Nt 3.0开启Memcached 以及二次开发监控Memcached状态
    Flex 中对xml数据的处理
    Oracle alert log 按天 存放 脚本
    Asktom Oracle:On Caching and Evangelizing SQL
  • 原文地址:https://www.cnblogs.com/csudanli/p/4844731.html
Copyright © 2011-2022 走看看