沒有經過處理的稀疏矩陣其實就是一個特殊的二維數組,數組中的大部分元素是0或者其他類型的非法值,只有少數幾個非零元素。
為了實現壓縮存儲,可以只存儲稀疏矩陣的非0元素。在存儲稀疏矩陣中的非0元素時,必須要存儲該元素的行列號以及元素值。
我們可以封裝一個三元組類來存儲這些元素。
//三元組
template<class T>
struct Triple
{
size_t _row; //行
size_t _col; //列
T _value; //值
Triple<T>::Triple() //定義無參的構造函數
{}
Triple(size_t row, size_t col,T value)
:_row(row)
, _col(col)
, _value(value)
{}
};
創建稀疏矩陣。利用容器,可以非常方便的存儲這些元素,相當於用一個動態數組來存儲。要求按照行優先的順序存儲,方便打印稀疏矩陣時,按照行列順序依次打印非0元素。
template<class T> //利用容器實現稀疏矩陣的壓縮存儲
SparseMatrix<T>::SparseMatrix(const T* array, size_t row, size_t col, const T& invalid) //初始化
:_rowMatrix(row)
, _colMatrix(col)
,_invalid(invalid)
{
for (size_t i = 0; i < _rowMatrix; ++i)
{
for (size_t j = 0; j < _colMatrix; ++j)
{
if (array[i*col + j] != invalid)
{
Triple<T> cur(i, j, array[i*col + j]);
_array.push_back(cur);
}
}
}
}
列序轉置法:以矩陣的列序進行轉置,這樣經過轉置后得到的三元組容器序列正好是以行優先存儲的。時間復雜度為 O(_colMatrix*_array.size())
template<class T> //列序轉置
SparseMatrix<T> SparseMatrix<T>::Transport()
{
assert(_array.size()!=0);
SparseMatrix<T> ret;
ret._rowMatrix = _colMatrix;
ret._colMatrix = _rowMatrix;
ret._invalid = _invalid;
ret._array.reserve(this->_array.size());
for (size_t j = 0; j < _colMatrix; j++)
{
size_t index = 0;
while (index < _array.size())
{
if (_array[index]._col == j)
{
Triple<T> tp(_array[index]._col, _array[index]._row, _array[index]._value);
ret._array.push_back(tp);
}
index++;
}
if (this->_array.size() == ret._array.size())
{
break;
}
}
return ret;
}
快速轉置法:事先確定矩陣每一列第一個元素在容器中的位置,在對稀疏矩陣轉置時,通過對原容器的遍歷,依次直接將元素放在新容器的恰當位置。時間復雜度為O(_colMatrix+_array.size())
轉置前,要先確定原矩陣每一列非零元素的個數,然后求出每一列非零元素在新容器中的正確位置。
設置兩個整型數組RowCounts[_colMatrix]、RowStart[_colMatrix]分別用來存放三元組容器中每一列非零元素的個數以及每一列第一個非零元素在新容器中的正確位置。
RowStart[0] = 0; RowStart[col] = RowStart[col - 1] + RowCounts[col - 1];
| 列號 | 0 | 1 | 2 | 3 | 4 |
| RowCounts[col] | 2 | 0 | 2 | 0 | 2 |
| RowStart[col] | 0 | 2 | 2 | 4 | 4 |
template<class T>
SparseMatrix<T> SparseMatrix<T>::FastTranaport() //快速轉置
{
assert(_array.size() != 0);
size_t index = 0;
SparseMatrix<T> ret;
ret._rowMatrix = _colMatrix;
ret._colMatrix = _rowMatrix;
ret._invalid = _invalid;
ret._array.resize(_array.size());
int *RowCounts = new int[_colMatrix];
int *RowStart = new int[_colMatrix];
memset(RowCounts, 0, _colMatrix*sizeof(int));
memset(RowStart, 0, _colMatrix*sizeof(int));
for (size_t i = 0; i < _array.size(); i++)
{
RowCounts[_array[i]._col]++;
}
RowStart[0] = 0;
for (size_t i = 1; i < _colMatrix; i++)
{
RowStart[i] = RowStart[i - 1] + RowCounts[i - 1];
}
Triple<T> tp;
for (size_t i = 0; i < _array.size(); i++)
{
tp._row = _array[i]._col;
tp._col = _array[i]._row;
tp._value = _array[i]._value;
ret._array[RowStart[_array[i]._col]++] = tp;
}
delete [] RowCounts;
delete [] RowStart;
return ret;
}
