疎行列-三元グループ


アルゴリズム思想は厳書から来ています.厳書に基づく三元組のデータ構造を実現します.勉強したいのは参考にしてください.
/*  Author : Moyiii
 *  Mail:  [email protected]
 *      -      
 *        ,         ,    。
 *      BUG,        ,      
*/
#include <iostream>
#include <cstdio>

using namespace std;

const int MAX_MATRIX_NUM = 100;
const int MAX_MATRIX_SIZE = 20;

//   
class Triple
{
public:
    int row;
    int col;
    int data;
};

//     
class SMatrix
{
public:
    void input();
    void copyMat(SMatrix &dest);
    //   
    static void addMat(SMatrix &a,SMatrix &b, SMatrix &dest);
    static void mulMat(SMatrix &a,SMatrix &b, SMatrix &dest);
    static void subMat(SMatrix &a,SMatrix &b, SMatrix &dest);
    static void countf(SMatrix &dest);
    //      
    void tran(SMatrix &dest);
    void print();
private:
    int nrow,ncol,nelems;
    //     ,         
    Triple datas[MAX_MATRIX_NUM];
    //              datas      
    int fpos[MAX_MATRIX_SIZE];
};

void SMatrix :: input()
{
     //          
    cout << "Please enter the num of row and colums:" ;
    cin >> nrow>> ncol;
    while(nrow < 0 || ncol < 0)
    {
        cout << "rows or colums must be positive integers" << endl;
        cout << "Please enter the num of row and colums:";
        cin >> nrow >> ncol;
    }
    cout << "Please input the num of non-zero elems:";
    cin >> nelems;
    while(nelems < 0 || nelems > MAX_MATRIX_NUM)
    {
        cout << "Num of nelems is invalid" << endl;
        cout << "Please input the num of non-zero elems:";
        cin >> nelems;
    }
    cout << "Please input n lines datas like: row col data:" << endl;
    for(int i = 0; i < nelems; ++i)
    {
        cin >> datas[i].row >>datas[i].col >> datas[i].data;
    }
    SMatrix :: countf(*this);
}

//  fpos  ,     。               
//           +         
void SMatrix :: countf(SMatrix &dest)
{
    int nums[dest.ncol];
    for(int i = 0; i < dest.ncol; ++i)
    {
        nums[i] = 0;
    }

    for(int i = 0; i < dest.nelems; ++i)
    {
        ++nums[dest.datas[i].row - 1];
    }

    dest.fpos[0] = 0;
    for(int i = 1; i <= dest.ncol; ++i)
    {
        dest.fpos[i] = dest.fpos[i-1] + nums[i-1];
    }
    dest.fpos[dest.nrow] = dest.nelems;
    return;
}

//          ,    
void SMatrix :: print()
{
    int index = 0;
    printf("  ");
    //       
    for(int i = 1; i <= ncol; ++i)
    {
        printf("%2d ",i);
    }
    printf("
"); printf(" "); for(int i = 1; i <= ncol; ++i) { printf("%2c ",'-'); } printf("
"); for(int i = 1; i <= nrow; ++i) { // printf("%d|",i); for(int j = 1; j <= ncol; ++j) { // if(index > nelems) { printf("%2d ",0); } else { // if(i == datas[index].row && j == datas[index].col) { printf("%2d ",datas[index].data); index++; } else { printf("%2d ",0); } } } cout << endl; } cout << endl; } // dest void SMatrix :: copyMat(SMatrix &dest) { if(&dest == this) { return; } for(int i = 0; i < this->nelems; ++i) { dest.datas[i] = this->datas[i]; } dest.nelems = this->nelems; dest.ncol = this->ncol ; dest.nrow = this->nrow ; for(int i = 0; i < nrow; ++i) { dest.fpos[i] = this->fpos[i]; } return; } // 。 。。 void SMatrix :: tran(SMatrix &dest) { Triple temp[MAX_MATRIX_NUM]; // int nums[ncol]; int tfpos[ncol]; for(int i = 0; i < ncol; ++i) { nums[i] = 0; } for(int i = 0; i <nelems; ++i) { ++nums[datas[i].col - 1]; } dest.fpos[0] = 0; tfpos[0] = 0; for(int i = 1; i <= ncol; ++i) { dest.fpos[i] = dest.fpos[i-1] + nums[i-1]; tfpos[i] = dest.fpos[i]; } int trows = this->ncol; int tcols = this->nrow; int telems = this->nelems; // , for(int i = 0; i < telems; ++i) { int &t = tfpos[this->datas[i].col - 1]; temp[t].col = this->datas[i].row; temp[t].row = this->datas[i].col; temp[t].data = this->datas[i].data; t++; } // , 。 for(int i = 0; i < telems; ++i) { dest.datas[i] = temp[i]; } dest.ncol = tcols; dest.nrow = trows; dest.nelems = telems; return; } // , 。 void SMatrix :: addMat(SMatrix &a,SMatrix &b, SMatrix &dest) { if(a.nrow != b.nrow || a.ncol != b.ncol) { cout << "Error, the two matrix are not the same size!" << endl; return; } int index = 0; int cura = 0,curb = 0; while(cura < a.nelems && curb < b.nelems) { int ra = a.datas[cura].row,rb = b.datas[curb].row; int ca = a.datas[cura].col,cb = b.datas[curb].col; // , if((ra-1)*a.nrow + ca < (rb-1)*b.nrow + cb) { dest.datas[index++] = a.datas[cura++]; } else if((rb-1)*b.nrow + cb <(ra-1)*a.nrow + ca) { dest.datas[index++] = b.datas[curb++]; } else { dest.datas[index] = a.datas[cura++]; dest.datas[index++].data += b.datas[curb++].data; if(dest.datas[index].data == 0) { index--; } } } while(cura < a.nelems) { dest.datas[index++] = a.datas[cura++]; } while(curb <b.nelems) { dest.datas[index++] = a.datas[curb++]; } dest.ncol = a.ncol; dest.nrow = a.nrow; dest.nelems = index; SMatrix :: countf(dest); return ; } // b -1, void SMatrix :: subMat(SMatrix &a,SMatrix &b, SMatrix &dest) { SMatrix temp; b.copyMat(temp); for(int i = 0; i < temp.nelems; ++i) { temp.datas[i].data *= -1; } SMatrix :: addMat(a,temp,dest); return; } void SMatrix :: mulMat(SMatrix &a,SMatrix &b, SMatrix &dest) { // a b , b , a b 。 // , SMatrix temp; b.tran(temp); int trow = a.nrow; int tcol = b.ncol; int index = 0; // , int res[tcol]; for(int i = 0; i < a.nrow; ++i) { //res i , 0 for(int k = 0; k < tcol; ++k) { res[k] = 0; } for(int j = 0; j < temp.nrow; ++j) { // M[i][j] int cura = a.fpos[i]; int curb = temp.fpos[j]; // , while(cura < a.fpos[i+1] && curb < temp.fpos[j+1]) { if(a.datas[cura].col < temp.datas[curb].col) { ++cura; } else if(temp.datas[curb].col < a.datas[cura].col) { ++curb; } else { res[j] += temp.datas[curb].data * a.datas[cura].data; curb++; cura++; } } } for(int k = 0; k < tcol ; ++k) { // if(res[k] != 0) { dest.datas[index].row = i + 1; dest.datas[index].col = k + 1; dest.datas[index].data = res[k]; index++; } } } dest.nelems = index; dest.nrow = trow; dest.ncol = tcol; SMatrix :: countf(dest); return ; } /* , 6 6 8 1 2 12 1 3 9 3 1 -3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7 */ int main() { SMatrix a; a.input(); a.print(); SMatrix b; b.input(); b.print(); SMatrix c; SMatrix :: mulMat(a,b,c); c.print(); return 0; }