十字链表稀疏矩阵

作者在 2010-05-12 22:01:28 发布以下内容
//KaKaMatrix.h文件

#pragma once
#include <iostream>
#include "math.h"
using namespace std;

typedef struct Matrix{
    int m;
    int n;
    double v;
    Matrix *Next;
    Matrix *Down;
    Matrix(int mm,int nn,double vv){
        m=mm;
        n=nn;
        v=vv;
        Next=Down=0;

    }
} *PMatrix;

class KaKaMatrix
{
public:
    KaKaMatrix(void);
    KaKaMatrix(int mm,int nn);
    KaKaMatrix(const KaKaMatrix& km);
    
public:
    void Init(int mm,int nn);
    void View(void);    
    int Insert(int mm, int nn, double vv);
    int Delete(int mm, int nn);    
    int Clear(void);
    int GetArray(double** PArr);
    int GetRow(void);
    int GetCol(void);
    bool IsSmall(double vv);
    double GetElement(int mm,int nn);
    KaKaMatrix MultNub(double km);
    KaKaMatrix Transpose(void);
    KaKaMatrix operator+(const KaKaMatrix& km);
    //KaKaMatrix operator*(const double km);
    KaKaMatrix operator*(const KaKaMatrix& km);
    KaKaMatrix& operator=(const KaKaMatrix& km);
public:
    ~KaKaMatrix(void);
    
private:
    int m,n,t;
    PMatrix *PMRow;
    PMatrix *PMCol;
    
};

ostream& operator<<(ostream& out,KaKaMatrix& km);//重载的输出操作符,可 cout<<KaKaMatrix 输

KaKaMatrix::KaKaMatrix(void):m(0),n(0),t(0),PMRow(new PMatrix[m]),PMCol(new PMatrix[n])
{
}

KaKaMatrix::KaKaMatrix(int mm,int nn)
{
    this->m =mm;
    this->n =nn;
    this->PMRow=new PMatrix[m];
    this->PMCol=new PMatrix[n];

    for(int i=0;i!=m;++i){
        PMRow[i]=0;
    }
    for(int i=0;i!=n;++i){
        PMCol[i]=0;
    }
    t=0;

}

KaKaMatrix::KaKaMatrix(const KaKaMatrix& km)
{
    //重载的拷贝构造函数
    this->m =km.m ;
    this->n =km.n;
    this->PMRow=new PMatrix[m];
    this->PMCol=new PMatrix[n];
    this->t=0;


    for(int i=0;i!=m;++i){
        PMRow[i]=0;
    }
    for(int i=0;i!=n;++i){
        PMCol[i]=0;
    }

    for(int i=0;i!=km.m;++i){
        PMatrix t_p=km.PMRow[i] ;
        while(t_p){
            this->Insert(t_p->m+1,t_p->n+1,t_p->v);
            
            t_p=t_p->Next ;

        }
    }

    

}

KaKaMatrix::~KaKaMatrix(void)
{
    this->Clear();

}

void KaKaMatrix::Init(int mm,int nn)//可用于,先定义一个空矩阵,再初始化
{
    //删除所有结点
    this->Clear();

    this->m =mm;
    this->n =nn;
    this->PMRow=new PMatrix[m];
    this->PMCol=new PMatrix[n];

    for(int i=0;i!=m;++i){
        PMRow[i]=0;
    }
    for(int i=0;i!=n;++i){
        PMCol[i]=0;
    }

}



int KaKaMatrix::Insert(int mm, int nn, double vv)
{
    --mm;
    --nn;
    if(vv==0.0) return 0;
    
    if((mm>=m||nn>=n)||(mm<0||nn<0)) return 0;

    PMatrix t_pp=0;//保存行插入时新结点指针,用于列插入
    
//行插入
    if(!this->PMRow[mm]){
        this->PMRow[mm]=new Matrix(mm,nn,vv);
        t_pp=this->PMRow[mm]->Next;//暂存

    }else{
        PMatrix t_p=this->PMRow[mm];

        while(t_p){
            if(t_p->n==nn){
                 t_p->v +=vv;
                 if(t_p->v==0.0){
                     //相加为零,删除结点
                     this->Delete(mm+1,nn+1);
                     return --t;

                 }
                
                 return t;
            }
            if((t_p->n<nn&&!t_p->Next)||(t_p->n<nn&&t_p->Next->n>nn)){
                t_p->Next=new Matrix(mm,nn,vv);
                t_pp=t_p->Next;
                return ++t;
            }
            t_p=t_p->Next ;
        }

    }
    //行插入结束,列插入开始

    if(!this->PMCol[nn]){
        this->PMCol[nn]=t_pp;

    }else{
        PMatrix t_p=this->PMCol[nn];

        while(t_p){
            if((t_p->m<mm&&!t_p->Down)||(t_p->m<mm&&t_p->Down->m>mm)){
                t_p->Down=t_pp;

            }
            t_p=t_p->Down ;

        }
    };
    return ++t;

    

}

int KaKaMatrix::Delete(int mm, int nn)
{
    //不带头结点,真是麻烦
    --mm;
    --nn;
    if((mm>=m||nn>=n)||(mm<0||nn<0)) return 0;

    PMatrix t_a = this->PMRow[mm] ;
    if(t_a&&(t_a->n==nn)){
        //删除第一行,第一列时出现的情况,不带头结点的缺点
        this->PMRow[mm]=this->PMRow[mm]->Next ;

    }else{
    
        while(t_a){
        
            if(t_a->n<nn&&t_a->Next->n==nn){            
            
                t_a->Next =t_a->Next->Next ;            
                break;
            }
        
            t_a=t_a->Next ;
        };
    }
    //

    PMatrix t_b=this->PMCol[nn];
    if(t_b&&(t_b->m ==mm)){

        PMatrix t_delete=t_b;
        t_b =t_b->Down;
        delete t_delete;
        return 1;


    }else{
        while(t_b){    
            if(t_b->m<mm&&t_b->Down->m==mm){            
                PMatrix t_delete=t_b->Down;
                t_b->Down =t_b->Down->Down ;
                delete t_delete;
                return 1;
            }        
            t_b=t_b->Next ;
       };

    }

    
    

    return 0;
}

int KaKaMatrix::Clear(void)
{
    //清空矩阵,全为0
    for(int i=0;i!=m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){

            PMatrix t_delete=t_p;
            t_p=t_p->Next ;
            delete t_delete;

        }
    }
    delete [] PMRow;
    delete [] PMCol;
    PMRow=PMCol=0;
    
    t=0;

    return 1;
}


KaKaMatrix KaKaMatrix::Transpose(void)
{
    //返回一个转置矩阵
    KaKaMatrix out_km(this->n,this->m);

    for(int i=0;i!=m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){
            out_km.Insert(t_p->n+1,t_p->m+1,t_p->v);
            t_p=t_p->Next ;

        }
    }

    return out_km;
}



void KaKaMatrix::View(void)
{
    //打印输出矩阵
    
//输出函数,空间复杂度 n*m ,时间复杂度不知道怎么算,执行循环总次数是 2*n*m+t+n。
    
//有没有更好的办法
    
//申请内存,全为0
    double **t_a=new double* [m];
    for(int i=0;i!=m;++i){
        t_a[i]=new double [n];
    }
    for(int i=0;i!=m;++i){
        for(int j=0;j!=n;++j){
            t_a[i][j]=0;
        }

    }
    //装填动态数组
    this->GetArray(t_a);

    cout<<endl<<"==========================================="<<endl;

    for(int i=0;i!=m;++i){
        
        for(int j=0;j!=n;++j){
            cout<<t_a[i][j]<<"  ";
        }
        cout<<endl;

    }
    cout<<"==========================================="<<endl;

    for(int i=0;i!=m;++i){
        delete [] t_a[i];
    }
    delete [] t_a;




        
}


int KaKaMatrix::GetRow(void)
{
    return m;
}

int KaKaMatrix::GetCol(void)
{
    return n;
}



KaKaMatrix KaKaMatrix::operator+(const KaKaMatrix& km)
{
    //重载矩阵加法
    if(km.m!=m||km.n!=n)
       return KaKaMatrix(0,0);
    KaKaMatrix out_km(m,n);

    for(int i=0;i!=km.m;++i){
        PMatrix t_p=km.PMRow[i] ;
        while(t_p){
            out_km.Insert(t_p->m+1,t_p->n+1,t_p->v);
            
            t_p=t_p->Next ;

        }
    }

    for(int i=0;i!=m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){
            out_km.Insert(t_p->m+1,t_p->n+1,t_p->v);
            t_p=t_p->Next ;

        }
    }

    return out_km;


}



KaKaMatrix& KaKaMatrix::operator=(const KaKaMatrix& km)
{
    //重载赋值操作
    
    this->Init(km.m,km.n);

    for(int i=0;i!=km.m;++i){
        PMatrix t_p=km.PMRow[i] ;
        while(t_p){
            this->Insert(t_p->m+1,t_p->n+1,t_p->v);
            
            t_p=t_p->Next ;

        }
    }



    return *this;
}



KaKaMatrix KaKaMatrix::operator*(const KaKaMatrix& km)
{
    if(n!=km.m)
      return KaKaMatrix(0,0);
    KaKaMatrix out_km(m,km.n);
    //把矩阵1装入数组
    double **t_a=new double* [m];
    for(int i=0;i!=m;++i){
        t_a[i]=new double [n];
    }
    for(int i=0;i!=m;++i){
        for(int j=0;j!=n;++j){
            t_a[i][j]=0;
        }

    }
    this->GetArray(t_a);

    //把矩阵2装入数组
    double **t_b=new double* [km.m];
    for(int i=0;i!=km.m;++i){
        t_b[i]=new double [km.n];
    }
    for(int i=0;i!=km.m;++i){
        for(int j=0;j!=km.n;++j){
            t_b[i][j]=0;
        }

    }
    for(int i=0;i!=km.m;++i){
        PMatrix t_p=km.PMRow[i] ;
        while(t_p){
            t_b[t_p->m][t_p->n]=t_p->v;
            t_p=t_p->Next ;

        }
    }

    //开始乘法
    
//结果矩阵两层循环
    for(int i=0;i!=m;++i){
        for(int j=0;j!=km.n;++j){
            double t_item=0;
            //核心循环
            for(int g=0;g!=n;++g){
                t_item+=t_a[i][g]*t_b[g][j];

            }

            out_km.Insert(i+1,j+1,t_item);
            
        }
    }

    return out_km;



}

int KaKaMatrix::GetArray(double** PArr)
{
    
    //装填动态数组
    for(int i=0;i!=m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){
            PArr[t_p->m][t_p->n]=t_p->v;
            t_p=t_p->Next ;

        }
    }
    return 1;
}
ostream& operator<<(ostream& out,KaKaMatrix& km){


    //重载的输出操作符,可 cout<<KaKaMatrix 输出。
    int m=km.GetRow();
    int n=km.GetCol();
    double **t_a=new double* [m];
    for(int i=0;i!=m;++i){
        t_a[i]=new double [n];
    }
    for(int i=0;i!=m;++i){
        for(int j=0;j!=n;++j){
            t_a[i][j]=0;
        }

    }
    //装填动态数组
    km.GetArray(t_a);

    out<<endl<<"==========================================="<<endl;

    for(int i=0;i!=m;++i){
        
        for(int j=0;j!=n;++j){
            out<<t_a[i][j]<<"  ";
        }
        out<<endl;

    }
    out<<"==========================================="<<endl;

    for(int i=0;i!=m;++i){
        delete [] t_a[i];
    }
    delete [] t_a;


    return  out;
}
KaKaMatrix KaKaMatrix::MultNub(double km)
{
    KaKaMatrix out_km(m,n);

    for(int i=0;i!=this->m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){
            out_km.Insert(t_p->m+1,t_p->n+1,t_p->v*km);
            
            t_p=t_p->Next ;

        }
    }
    return out_km;
    /*for(int i=0;i!=m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){
            t_p->v = t_p->v*km;
            t_p=t_p->Next;
        }
    }
    return ;
*/
}

double KaKaMatrix::GetElement(int mm, int nn)
{
    --mm;
    --nn;
    if((mm>=m||nn>=n)||(mm<0||nn<0)) return 0;
    
    PMatrix t_p = this->PMRow[mm];
    while(t_p){
        if(t_p->n == nn)
            return t_p->v;
        
        t_p=t_p->Next;
    }

    return 0;
}

bool KaKaMatrix::IsSmall(double vv)
{
    for(int i=0;i!=this->m;++i){
        PMatrix t_p=this->PMRow[i] ;
        while(t_p){
            if(abs(t_p->v) > vv)
                return false;
            t_p=t_p->Next;
        }
    }
    return true;
}
修改于网上一个大牛的十字链表稀疏矩阵
修改了矩阵乘法bug
添加取元素操作
修改了其他一些小bug
 
乘法操作的时间和空间复杂度比较高,本来想改的,怕破坏了人家漂亮的结构,就算了。
默认分类 | 阅读 2299 次
文章评论,共0条
游客请输入验证码
浏览255646次