特殊矩阵的压缩存储

矩阵的格式采用二维数组进行存储,接下来本文将介绍一些特殊矩阵的压缩存储方法。

1.对称矩阵

对称矩阵中的元素有一定的规律,就是行下标row与列下标col 互换后得到的新坐标的元素与换坐标前的元素相同。因此我们在存放对称矩阵的元素时只需将它的下三角或上三角的元素存储就可以了。特殊矩阵也称上三角矩阵或者下三角矩阵。

采用行优先进行存储:

对于下三角矩阵,原数组元素a[i][j]与压缩数组原则b[k]的对应关系如下:

  • k = i * (i - 1) / 2 + j - 1

 对于上三角矩阵,原数组元素a[i][j]与压缩数组原则b[k]的对应关系如下:

  • k = (i - 1) * (2n - i  + 2) / 2 + j - i

基于此设计的代码如下:

//
// Created by A on 2023/6/13.
//
#include<iostream>
#include<vector>
#include<assert.h>

using namespace std;

template<class T>
class SymmetricMatrix {
public:
    SymmetricMatrix(size_t row, size_t col, T *array)
            : _row(row), _col(col) {
        int index = 0;
        _v.resize(((1 + row) * row) >> 1);
        for (size_t i = 0; i < row; i++)
            for (size_t j = 0; j <= i; j++)
                _v[index++] = array[i * col + j];

    }

    T &Aescc(size_t row, size_t col) {
        if (row < col)
            swap(row, col);
        return _v[(((row + 1) * row) >> 1) + col];
    }

    void BackSymmetricMatrix() {
        for (size_t i = 0; i < _row; i++) {
            for (size_t j = 0; j < _col; j++) {
                cout << Aescc(i, j) << " ";
            }
            cout << endl;
        }
    }

private:
    vector<T> _v;
    size_t _row;
    size_t _col;
};

int main() {
    int a[5][5] = {
            {0, 1, 2, 3, 4},
            {1, 0, 1, 2, 3},
            {2, 1, 0, 1, 2},
            {3, 2, 1, 0, 1},
            {4, 3, 2, 1, 0}};

    SymmetricMatrix<int> sm(5, 5, (int *) a);
    int ret = sm.Aescc(2, 1);
    cout << ret << endl;
    ret = sm.Aescc(0, 3);
    cout << ret << endl;
    sm.BackSymmetricMatrix();

    system("pause");
    return 0;
}

 运行结果如下:

1
3
0 1 2 3 4
1 0 1 2 3
2 1 0 1 2
3 2 1 0 1
4 3 2 1 0

2.稀疏矩阵

稀疏矩阵是指矩阵中大多数元素为0的矩阵。从直观上来讲,当非零元素低于总元素的30%时,这样的矩阵称为稀疏矩阵。

本文对于稀疏矩阵采用三元组法进行存储。则我们要创建一个包含它的行坐标row 列坐标col 与元素 data 的结构体。

代码如下:
 

//
// Created by A on 2023/6/13.
//
#include<iostream>
#include<vector>
#include<assert.h>
#include<string.h>

using namespace std;

template<class T>
class SparseMatrix {
public:
    template<class >
    struct Trituple{
        Trituple(size_t row = 0, size_t col = 0, const T &data = T())
                : _row2(row), _col2(col), _data(data) {}

        size_t _row2;
        size_t _col2;
        T _data;
    };

    SparseMatrix() {}

    SparseMatrix(T *_array, size_t row, size_t col)
            : _row(row), _col(col), invaild(0) {
        for (size_t i = 0; i < row; i++) {
            for (size_t j = 0; j < col; j++) {
                if (_array[i * col + j] != invaild)
                    _vm.push_back(Trituple<T>(i, j, _array[i * col + j]));
            }
        }
    }

    T &Aescc(size_t row, size_t col) {
        for (size_t i = 0; i < _vm.size(); i++) {
            if (_vm[i]._row2 == row && _vm[i]._col2 == col)
                return _vm[i]._data;
        }
        return invaild;
    }

    void displaySparseMatrix(){
        size_t index = 0;
        for (size_t i = 0; i < _row; i++) {
            for (size_t j = 0; j < _col; j++) {
                if (index < _vm.size() && _vm[index]._row2 == i && _vm[index]._col2 == j) {
                    cout << _vm[index]._data << " ";
                    index++;
                } else
                    cout << invaild << " ";
            }
            cout << endl;
        }
    }

    void ReverseMatrix(){
        for (size_t i = 0; i < _col; i++) {
            for (size_t j = 0; j < _row; j++) {
                int flag = 0;
                size_t index = _vm.size();
                while (index--) {
                    if (_vm[index]._row2 == j && _vm[index]._col2 == i) {
                        flag = 1;
                        cout << _vm[index]._data << " ";
                    }
                }
                if (flag == 0)
                    cout << invaild << " ";
            }
            cout << endl;
        }
    }

    friend ostream &operator<<(ostream &_cout, SparseMatrix<T> &m) {
        size_t index = 0;
        for (size_t i = 0; i < m._row; i++) {
            for (size_t j = 0; j < m._col; j++) {
                if (index < m._vm.size() && m._vm[index]._row2 == i && m._vm[index]._col2 == j) {
                    _cout << m._vm[index]._data << " ";
                    index++;
                } else
                    _cout << m.invaild << " ";
            }
            cout << endl;
        }
        return _cout;
    }

    SparseMatrix<T> &operator+(SparseMatrix<T> &d){
        assert(d._row == _row && d._col == _col);
        SparseMatrix<T> *tmp = new SparseMatrix<T>;
        (*tmp)._col = _col;
        (*tmp)._row = _row;
        (*tmp).invaild = invaild;

        size_t leftMatrix = 0;
        size_t rightMatrix = 0;
        size_t Addrleft = 0;
        size_t Addrright = 0;
        while (leftMatrix < _vm.size() && rightMatrix < d._vm.size()) {
            Addrleft = _vm[leftMatrix]._row2 * _col + _vm[leftMatrix]._col2;
            Addrright = d._vm[rightMatrix]._row2 * _col + d._vm[rightMatrix]._col2;
            if (Addrleft > Addrright) {
                (*tmp)._vm.push_back(d._vm[rightMatrix]);
                rightMatrix++;
            } else if (Addrleft < Addrright) {
                (*tmp)._vm.push_back(_vm[leftMatrix]);
                leftMatrix++;
            } else {
                Trituple<T> ret;
                ret._col2 = _vm[leftMatrix]._col2;
                ret._row2 = _vm[leftMatrix]._row2;
                ret._data = _vm[leftMatrix]._data + d._vm[rightMatrix]._data;
                if (ret._data != invaild)
                    (*tmp)._vm.push_back(ret);
                leftMatrix++;
                rightMatrix++;
            }
        }
        while (leftMatrix < _vm.size()) {
            (*tmp)._vm.push_back(_vm[leftMatrix]);
            leftMatrix++;
        }
        while (rightMatrix < d._vm.size()) {
            (*tmp)._vm.push_back(d._vm[rightMatrix]);
            rightMatrix++;
        }
        return (*tmp);
    }


    SparseMatrix<T> &FastReverseMatrix(){
        SparseMatrix<T> *Newm = new SparseMatrix<T>;
        (*Newm)._row = _col;
        (*Newm)._col = _row;
        (*Newm).invaild = invaild;
        (*Newm)._vm.resize(_vm.size());

        int *count = new int[_col];
        memset(count, 0, _col * sizeof(int));
        for (size_t i = 0; i < _vm.size(); i++)
            count[_vm[i]._col2]++;
        int *addr = new int[_col];
        memset(addr, 0, _col * sizeof(int));
        for (size_t i = 1; i < _col; i++)
            addr[i] = addr[i - 1] + count[i - 1];
        for (size_t i = 0; i < _vm.size(); i++) {
            int &rowAddr = addr[_vm[i]._col2];
            (*Newm)._vm[rowAddr] = _vm[i];
            swap((*Newm)._vm[rowAddr]._row2, (*Newm)._vm[rowAddr]._col2);
            rowAddr++;
        }
        return (*Newm);
    }


private:
    vector <Trituple<T>> _vm;
    size_t _row;
    size_t _col;
    T invaild;
};

void test1(){
    int array1[6][5] = {
            {1, 0, 3, 0, 5},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0},
            {1, 0, 3, 0, 5},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0}};
    SparseMatrix<int> sn1((int *) array1, 6, 5);   //存储一个稀疏矩阵
    sn1.displaySparseMatrix();     //打印稀疏矩阵
    cout << endl;

    int array2[6][5] = {
            {0, 0, 3,  0, 5},
            {0, 2, 0,  0, 0},
            {0, 0, 0,  0, 0},
            {5, 0, -3, 0, 5},
            {0, 4, 0,  0, 0},
            {2, 0, 0,  0, 0}};
    SparseMatrix<int> sn2((int *) array2, 6, 5);   //存储一个稀疏矩阵
    cout << sn2 << endl;
    SparseMatrix<int> sn3 = sn1 + sn2;
    cout << sn3;

}

void test2(){
    int array1[6][5] = {
            {1, 0, 3, 0, 5},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0},
            {1, 0, 3, 0, 5},
            {0, 0, 0, 0, 0},
            {0, 0, 0, 0, 0}};
    SparseMatrix<int> sn1((int *) array1, 6, 5);
    SparseMatrix<int> sn2 = sn1.FastReverseMatrix();
    cout << sn2;
}

int main() {

    test1();
    test2();
    system("pause");
    return 0;
}

运行结果如下:

1 0 3 0 5
0 0 0 0 0
0 0 0 0 0
1 0 3 0 5
0 0 0 0 0
0 0 0 0 0

0 0 3 0 5
0 2 0 0 0
0 0 0 0 0
5 0 -3 0 5
0 4 0 0 0
2 0 0 0 0

1 0 6 0 10
0 2 0 0 0
0 0 0 0 0
6 0 0 0 10
0 4 0 0 0
2 0 0 0 0
1 0 0 1 0 0
0 0 0 0 0 0
3 0 0 3 0 0
0 0 0 0 0 0
5 0 0 5 0 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值