1. 程式人生 > >資料結構-稀疏矩陣(壓縮儲存,轉置,加法,乘法)類庫

資料結構-稀疏矩陣(壓縮儲存,轉置,加法,乘法)類庫

上完資料結構課,練練手~

個人能力問題,可能會有少許bug,畢竟本人debug這個程式碼用了2天的空閒時間...

目前本人測試沒有問題...記錄一下,方便以後整理,更新程式碼, debug。

-----------------

程式碼用了兩個class分別封裝Matrix和record,record為壓縮矩陣的記錄,記錄了一個元素的位置以及資料內容。Matrix則記錄矩陣的資料(record封裝),大小,以及轉置要用到的cpot陣列,也就是記錄從第一列到第n列,共有多少個元素。

程式碼中cpot由0開始,方便書寫程式碼。而資料結構書中(清華大學那本)是以1開頭的,大家要用的話也可以注意一下。

程式碼裡也含有大量debug輸出語句,要檢視資料可以呼叫輸出函式或去除註釋。

#include <iostream>

using namespace std;

typedef int ET;

class record {
public:
    record()
    {
        this->posx = 0;
        this->posy = 0;
        this->data = 0;
    }
    record(int posx, int posy, ET data)
    {
        this->posx = posx;
        this->posy = posy;
        this->data = data;
    }
    int get_x()
    {
        return posx;
    }
    int get_y()
    {
        return posy;
    }
    ET get_data()
    {
        return data;
    }
    void edit_x(int x)
    {
        this->posx = x;
    }
    void edit_data(ET data)
    {
        this->data = data;
    }
    void edit_y(int y)
    {
        this->posy = y;
    }
private:
    int posx;
    int posy;
    ET data;
};

class Matrix
{
public:
    int tmp_input;
    Matrix()
    {
        int x, y;
        cout << "Input \"x and y\" size in Matrix : ";
        cin >> x >> y;
        this->store_x(x);
        this->store_y(y);
        this->set_size_malloc(x*y);
        this->init_num_array(x*y);
    }
    Matrix(int x, int y)
    {
        this->store_x(x);
        this->store_y(y);
        this->set_size_malloc(x*y);
        this->init_num_array(x*y);
    }
    void init_num_array(int _size)
    {
        this->cpot = new int[y_size];
        //(int*)malloc(y_size* sizeof(int));
    }
    void set_size_malloc(int _size)
    {
        this->point = 0;
        this->mat_size = _size;
        this->r = new record[_size];
        //(record*)malloc(sizeof(record)*_size);
    }
    void store_x(int x)
    {
        this->x_size = x;
    }
    void store_y(int y)
    {
        this->y_size = y;
    }
    int get_x()
    {
        return this->x_size;
    }
    int get_y()
    {
        return this->y_size;
    }
    record* get_record()
    {
        return this->r;
    }
    void store_record(record record_piece)
    {
        r[point] = record_piece;
    }
    int get_point()
    {
        return this->point;
    }
    void edit_point(int point)
    {
        this->point = point;
    }
    void input() {
        //memset(num, 0, y_size * sizeof(int));
        for (int j = 0; j < x_size; j++)
            for (int k = 0; k < y_size; k++) {
                cin >> tmp_input;
                if (tmp_input != 0) {
                    this->store_record(record(j, k, tmp_input));
                    ++point;
                }
                else {
                    continue;
                }
            }
        //calc cpot(num first)
        //cout << "Output num[]:" << endl;
        //for (int i = 0; i < y_size; ++i)
        //{
        //    cout << num[i] << " ";
        //}
        cout << endl;
        calc_cpot();
        //output_cpot();
    }


    int* calc_num()
    {
        int *num = new int[mat_size] {0};
        for (int p = 0; p < point; ++p) {
            int y = r[p].get_y();
            num[y]++;
        }
        return num;
    }



    void calc_cpot()
    {
        /*calc cpot(num first)
        -> calc cpot
        */
        int *num = calc_num();
        cpot[0] = 0;
        for (int i = 1; i < y_size; ++i)
        {
            cpot[i] = num[i - 1] + cpot[i - 1];
            //*(cpot + i * sizeof(int)) = num[i-1] + *(cpot + (i-1) * sizeof(int));
        }
        delete(num);
    }
    void output_record()
    {
        cout << endl<< "Output record:" << endl << "X-------Y-------Data" << endl;
        for (int i = 0; i < point; ++i)
        {
            record* o_r = &r[i];
            cout << o_r->get_x() << " " << o_r->get_y() << " " << o_r->get_data() << endl;
        }
        cout << endl << "========Output record End=========" << endl;

    }
    void output_cpot() {
        cout << "Output cpot(-1):" << endl;
        for (int i = 0; i < y_size; ++i) {
            cout << this->cpot[i] << " ";
        }
        cout << endl;
    }

    Matrix transpose()
    {
        Matrix T=Matrix(get_y(),get_x());
        //cout << endl << "========Transpose Start=========" << endl;
        T.edit_point(this->point);
        //convert pos
        //this->output_cpot();
        for (int p = 0; p < point; ++p)
        {
            int col = r[p].get_y();
            //(r+ sizeof(record) * p)->get_y();
            int convert_col = this->cpot[col];
            //*(cpot+ col * sizeof(int));
            record* m2 = &T.get_record()[convert_col];
            //(mat2.get_record()+((sizeof(record))*convert_col));
            m2->edit_x(col);
            m2->edit_y(r[p].get_x()
                    //(r+ sizeof(record) * p)->get_x()
            );
            m2->edit_data(r[p].get_data()
                    //(r+ sizeof(record) * p)->get_data()
            );
            this->cpot[col] = this->cpot[col] + 1;
            //*(cpot+ col*sizeof(int))=*(cpot+ col*sizeof(int))+1;
        }
        T.calc_cpot();
        //mat2.output_cpot();
        this->calc_cpot();
        //mat2.output_record();
        //cout << endl << "========Transpose End=========" << endl;
        return T;
    }

    Matrix multiply(Matrix mat2)
    {
        //judge if can be multiplied
        if(this->get_x()==mat2.get_y() && this->get_y()==mat2.get_x()) {
            Matrix T= Matrix(get_x(),mat2.get_y());
            //point
            int value[this->get_x()][mat2.get_y()];
            memset(value,0, sizeof(value));
            for (int j=0;j<point;++j) {
                for(int k=0;k<mat2.get_point();++k){
                    if(r[j].get_y()!=mat2.get_record()[k].get_x())
                        continue;
                    //debug mode
                    //cout<<"value["<<r[j].get_x()<<"]["<<mat2.get_record()[k].get_y()<<"]+=Mat1("
                    //           <<r[j].get_x()<<","<<r[j].get_y()<<") *"<<" Mat2("
                    //                                           <<mat2.get_record()[k].get_x()<<","<<mat2.get_record()[k].get_y()<<") \'s Data."<<endl;
                    //cout<<"data1:"<<r[j].get_data()<<" data2:"<<mat2.get_record()[k].get_data()<<endl<<endl;
                    //
                    value[r[j].get_x()][mat2.get_record()[k].get_y()]+=
                            r[j].get_data() * mat2.get_record()[k].get_data();
                }
            }
            for (int j=0;j<this->get_x();++j){
                for(int k=0;k<mat2.get_y();++k){
                    if(value[j][k]!=0){
                        //debug mode
                        //cout<<value[j][k]<<" ";
                        //
                        T.store_record(record(j,k,value[j][k]));
                        T.edit_point(T.get_point()+1);
                    } else continue;
                }
            }
            return T;
        }
        else
        {
            cout<<"It's cannot be multiplied by the Matrix you input."<<endl;
            return {0,0};
        }
    }

    Matrix add(Matrix mat2)
    {
        //judge if can be added
        if(this->get_x()==mat2.get_x() && this->get_y()==mat2.get_y()) {
            Matrix T= Matrix(get_x(),mat2.get_y());
            //point
            int value[this->get_x()][mat2.get_y()];
            memset(value,0,sizeof(value));
            for (int j=0;j<point;++j) {
                for(int k=0;k<mat2.get_point();++k){
                    if(r[j].get_x()!=mat2.get_record()[k].get_x() || r[j].get_y()!=mat2.get_record()[k].get_y())
                        continue;
                    //debug mode
                    //cout<<"value["<<r[j].get_x()<<"]["<<mat2.get_record()[k].get_y()<<"]+=Mat1("
                    //           <<r[j].get_x()<<","<<r[j].get_y()<<") *"<<" Mat2("
                    //                                           <<mat2.get_record()[k].get_x()<<","<<mat2.get_record()[k].get_y()<<") \'s Data."<<endl;
                    //cout<<"data1:"<<r[j].get_data()<<" data2:"<<mat2.get_record()[k].get_data()<<endl<<endl;
                    //
                    value[r[j].get_x()][mat2.get_record()[k].get_y()]=
                            r[j].get_data() + mat2.get_record()[k].get_data();
                }
            }
            for (int j=0;j<this->get_x();++j){
                for(int k=0;k<mat2.get_y();++k){
                    if(value[j][k]!=0){
                        //debug mode
                        //cout<<value[j][k]<<" ";
                        //
                        T.store_record(record(j,k,value[j][k]));
                        T.edit_point(T.get_point()+1);
                    } else continue;
                }
            }
            return T;
        }
        else
        {
            cout<<"It's cannot be added by the Matrix you input."<<endl;
            return {0,0};
        }
    }

    void show(){
        int tmp_point=0;
        for(int j=0;j<get_x();++j){
            for(int k=0;k<get_y();++k){
                if(r[tmp_point].get_x()==j && r[tmp_point].get_y()==k){
                    cout<<r[tmp_point].get_data()<<" ";
                    ++tmp_point;
                }
                else cout<<"0 ";
            }
            cout<<endl;
        }


    }


private:
    int x_size;
    int y_size;
    int mat_size;
    int *cpot;
    int point;
    record* r;
};

int main()
{
    Matrix mat1 = Matrix();
    mat1.input();
    Matrix mat2 = mat1.transpose();
    Matrix mat3=mat2.transpose();
    //mat.output_record();
    //mat.output_cpot();


    cout << "This is mat1(User's Input)" << endl;
    mat1.show();


    cout << "This is mat2(transpose mat1):" << endl;
    mat2.show();


    cout << "This is mat3(transpose mat2)" << endl;
    mat3.show();


    cout << "This is mat4(mat1 * mat2)" << endl;
    Matrix mat4=mat1.multiply(mat2);
    mat4.show();

    cout << "This is mat5(mat1 + mat3)" << endl;
    Matrix mat5=mat1.add(mat3);
    mat5.show();

    return 0;
}

/*
測試資料:
========test1======
6 7
0 12 9 0 0 0 0
0 0 0 0 0 0 0
-3 0 0 0 0 14 0
0 0 24 0 0 0 0
0 18 0 0 0 0 0
15 0 0 -7 0 0 0
===================
===========test2=====
3 3
5 6 7
8 9 1
0 0 0
========================
*/