您好,登錄后才能下訂單哦!
假設在m*n的矩陣中,有t個元素不為0。令稀疏因子s=t/(m*n),通常認為s<0.05時稱為稀疏矩陣。
有時為了節省存儲空間,可以對這類矩陣進行壓縮存儲。所謂的壓縮存儲就是,為多個相同的值分配存儲在一個空間,對零元不分配空間。而稀疏矩陣是只存儲有效值,無效值只分配一個空間。
在這里我們用一個順序表vector存儲稀疏矩陣的有效值的行,列,值三個元素。
struct Triple { int _cow; int _col; T _value; Triple(int cow,int col,T value) :_cow(cow) , _col(col) , _value(value) {} Triple() :_cow(0) , _col(0) { } };
class SparseMatrix { public: SparseMatrix(T* a, int m, int n, const T& invalid) :_cow(m) , _col(n) , _invalue(invalid) { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (a[i*n + j] != invalid) { Triple<T> tmp(i, j, a[i*n + j]); _a.push_back(tmp); } } } } protected: vector<Triple<T>> _a; int _cow;//矩陣行數 int _col;//矩陣列數 T _invalue;//無效值 };
下面我們來討論一下稀疏矩陣的轉置,轉置運算時最簡單的一種矩陣運算。要得到轉置矩陣,我們只要做到三點。
將矩陣的行列值相互交換
每個三元組的i和j相互交換
重排三元組之間的次序便可以實現轉置
SparseMatrix<T> Transport() { SparseMatrix<T> tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; for (size_t i = 0; i < _col; ++i)//遍歷每一列,找到每一列有效值 { size_t index = 0; while (index < _a.size()) { if (_a[index]._col == i) { Triple<T> tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a.push_back(tp); } index++; } } return tmp; }
對于矩陣的轉置,我們首先得要了解轉置后行列的變化。轉置前的行變成了轉置后的列。對于三元組順序表中的元素是遵循行優先存儲的。所以要得到轉置后的每一行的有效值,只要循環遍歷轉置前的每一列即可。
矩陣的轉置可以優化,使用快速轉置。
SparseMatrix<T> FastTransport() { SparseMatrix<T> tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; tmp._a.resize(_a.size()); int* cowCount = new int[_col]; int* cowStart = new int[_col]; memset(cowCount, 0, sizeof(int)*_col); memset(cowStart, 0, sizeof(int)*_col); size_t index = 0; while (index < _a.size()) { cowCount[_a[index++]._col]++; cowStart[0]; for (size_t i = 1; i < _col; ++i) { cowStart[i] = cowStart[i - 1] + cowCount[i - 1]; } } index = 0; while (index < _a.size()) { int& cowBegin = cowStart[_a[index]._col]; Triple<T> tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a[cowBegin] = tp; cowBegin++; index++; } return tmp; }
快速轉置的思想是開辟兩個數組用來存每一行有效值的個數,另一個用來存每個有效值在轉置后順序表vector中的起始位置。使用數組可以快速找到有效數據在轉置后順序表中的位置
以下是完整代碼:
#pragma once #include<iostream> #include<vector> using namespace std; template<class T> struct Triple { int _cow; int _col; T _value; Triple(int cow,int col,T value) :_cow(cow) , _col(col) , _value(value) {} Triple() :_cow(0) , _col(0) { } }; template<class T> class SparseMatrix { public: SparseMatrix(T* a, int m, int n, const T& invalid) :_cow(m) , _col(n) , _invalue(invalid) { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (a[i*n + j] != invalid) { Triple<T> tmp(i, j, a[i*n + j]); _a.push_back(tmp); } } } } SparseMatrix() :_cow(0) , _col(0) {} SparseMatrix<T> Transport() { SparseMatrix<T> tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; for (size_t i = 0; i < _col; ++i) { size_t index = 0; while (index < _a.size()) { if (_a[index]._col == i) { Triple<T> tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a.push_back(tp); } index++; } } return tmp; } SparseMatrix<T> FastTransport() { SparseMatrix<T> tmp; tmp._cow = _col; tmp._col = _cow; tmp._invalue = _invalue; tmp._a.resize(_a.size()); int* cowCount = new int[_col]; int* cowStart = new int[_col]; memset(cowCount, 0, sizeof(int)*_col); memset(cowStart, 0, sizeof(int)*_col); size_t index = 0; while (index < _a.size()) { cowCount[_a[index++]._col]++; cowStart[0]; for (size_t i = 1; i < _col; ++i) { cowStart[i] = cowStart[i - 1] + cowCount[i - 1]; } } index = 0; while (index < _a.size()) { int& cowBegin = cowStart[_a[index]._col]; Triple<T> tp; tp._col = _a[index]._cow; tp._cow = _a[index]._col; tp._value = _a[index]._value; tmp._a[cowBegin] = tp; cowBegin++; index++; } return tmp; } void Display() { size_t index = 0; for (int i = 0; i < _cow; i++) { for (int j = 0; j < _col; j++) { if (index < _a.size()//此處必須加index<_a.size()這個條件, //并且在最前面訪問到最后一個有效值后再_a[index]會訪問越界 &&_a[index]._cow == i && _a[index]._col == j) { cout << _a[index]._value << " "; ++index; } else { cout << _invalue << " "; } } cout << endl; } cout << endl; } protected: vector<Triple<T>> _a; int _cow;//矩陣行數 int _col;//矩陣列數 T _invalue; };
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。