您的位置:首页 > 其它

稀疏矩阵的转置和快速转置

2016-03-11 01:23 274 查看
稀疏矩阵压缩存储:

代码:

#pragma once

#include<vector>
using namespace std;

template<class T>
struct Triple
{
Triple()
{}
Triple(T & v, int r, int c)
:_value(v)
, _row(r)
, _col(c)
{}
size_t _row;
size_t _col;
T _value;
};

//稀疏矩阵的压缩存储
template<class T>
class SparseMatrix
{
public:
SparseMatrix()
:_RowSize(0)
, _ColSize(0)
{
}
SparseMatrix(T * a, size_t row, size_t col,const T & invalid)
:_RowSize(row)
, _ColSize(col)
, _invalid(invalid)
{
for (size_t i = 0; i < _RowSize; ++i)
{
for (size_t j = 0; j < _ColSize; j++)
{
if (a[i*_ColSize + j] != invalid)
{
Triple<T> t(a[i*_ColSize + j], i, j);
_array.push_back(t);
}
}
}
}

void Display()
{
size_t index = 0;
for (size_t i = 0; i < _RowSize; ++i)
{
for (size_t j = 0; j < _ColSize; j++)
{
if (index<_array.size()&&_array[index]._row==i &&_array[index]._col==j )
{
cout << _array[index++]._value << " ";
}
else
{
cout << _invalid<<" ";
}
}
cout << endl;
}
cout << endl;
}
private:
vector<Triple<T>> _array;
size_t _RowSize;
size_t _ColSize;
T _invalid;  //非法值
};
//转置算法为成员函数,在下面列出

一般转置算法:从保存矩阵的数组中抽取列为index的元素,转换行列值后,插入到新的矩阵中,经过列数col次迭代,即可完成转置。

完整代码如下:

SparseMatrix<T> Transpose()  //转置
{
SparseMatrix sm;
sm._RowSize = _ColSize;
sm._ColSize = _RowSize;
sm._invalid = _invalid;
int i=0;
for (int j = 0; j < _ColSize; ++j)
{
i = 0;
while ( i < _array.size())
{
if (j == _array[i]._col)
{
Triple<T> t(_array[i]._value, _array[i]._col, _array[i]._row);
sm._array.push_back(t);
}
++i;
}
}
return sm;
//O(有效元素数*列数)
}
<pre name="code" class="cpp">




快速转置算法:经过常数次运算,求出转置后,每行的起始位置,之后遍历一次存储矩阵的数组进行迭代插入,这样可以在O(n)的时间复杂度下完成转置。

SparseMatrix<T> Transpose()  //转置
{
SparseMatrix sm;
sm._RowSize = _ColSize;
sm._ColSize = _RowSize;
sm._invalid = _invalid;
int i=0;
for (int j = 0; j < _ColSize; ++j)
{
i = 0;
while ( i < _array.size())
{
if (j == _array[i]._col)
{
Triple<T> t(_array[i]._value, _array[i]._col, _array[i]._row);
sm._array.push_back(t);
}
++i;
}
}
return sm;
//O(有效元素数*列数)
}
SparseMatrix<T> FastTranspose() //快速转置
{
SparseMatrix sm;
sm._ColSize = _RowSize;
sm._RowSize = _ColSize;
sm._invalid = _invalid;
sm._array.resize(_array.size()); //这块会调用默认构造函数 所以Triple必须默认构造函数
int index = 0;
int* RowCount = new int[_ColSize];
int* RowStart = new int[_ColSize];
memset(RowCount, 0, sizeof(int)*_ColSize);
memset(RowStart, 0, sizeof(int)*_ColSize);

while (index < _array.size()) //一次迭代O(n)
{
++RowCount[_array[index++]._col];
}
index = 1;
while (index < _ColSize) //O(n)
{
RowStart[index] = RowStart[index - 1] + RowCount[index - 1];
++index;
}

//执行快速转置
int i = 0;
while (i < _array.size()) //两次迭代 O(n)
{

Triple<T> t(_array[i]._value, _array[i]._col, _array[i]._row);
sm._array[RowStart[_array[i]._col]++] = t;
++i;
}

delete[] RowCount;
delete[] RowStart;

return sm;

//时间复杂度O(有效元素数*常数次迭代)
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: