稀疏矩阵-压缩存储-列转置法- 一次定位快速转置法

稀疏矩阵的压缩存储

压缩存储值存储极少数的有效数据。使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放。

压缩存储:行优先一行一行扫 有效数据存入以为矩阵_arr

列转置法 : 从前向后遍历压缩矩阵,先找列号为0的存入 转置矩阵的压缩矩阵.然后从前向后找列号为1的 。。。直到转置矩阵的压缩矩阵大小和 原矩阵的一样大 这时就找完了

时间复杂度为    O(原矩阵列数 * 压缩矩阵长度)

一次定位快速转置法:

设置两个辅助矩阵 RowCounts 和 RowStart

RowCounts 记录 原矩阵每列的有效元素元素的个数 (这里Row指的是转置矩阵的行 RowCount指的也就是转置矩阵 的 行有效元个数)

RowStart 记录的是  原矩阵 每列首个有效元素 在 转置矩阵 的压缩矩阵中的坐标 (也就是 转置矩阵 的 每行首个有效元素 在 转置矩阵 的压缩矩阵中的 坐标)

RowStart[n]可以由 RowCount[n-1]和上一个RowStart[n-1]求得 n>0

RowStart[0] = 0;

利用 RowStart 可以实现 由 原矩阵 的压缩矩阵元素 到 转置矩阵的压缩矩阵 的一次快速定位

如:

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>

#include <assert.h>

#include <vector>

#include <string>

using namespace std;

/***

*

* 稀疏矩阵

* 压缩存储

* 转置 (一般 和 快速转置)

* 2016-4-18

* bozi

******************/

// 三元组

template<class T>

struct Triple

{

size_t _row;

size_t _col;

T _value;

Triple()

{}

Triple(size_t row, size_t col, T value)

:_row(row)

,_col(col)

,_value(value)

{}

};

// 稀疏矩阵

template<class T>

class SparesMatrix

{

public:

SparesMatrix();

SparesMatrix(const T* array, size_t row, size_t col, const T& invalid);

SparesMatrix<T> Transport(); //列转置

SparesMatrix<T> FastTransport(); //快速转置

void Display() const;

protected:

vector<Triple<T> > _array; // 动态数组存储稀疏矩阵

size_t _rowMatrix;

size_t _colMatrix;

T _invalid; // 定义的无效值

};

template<class T>

SparesMatrix<T>::SparesMatrix()

{}

template<class T>

SparesMatrix<T>::SparesMatrix(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)

{

// _array.push_back({i, j, array[i * col + j]});

_array.push_back(Triple<T>(i, j, array[i * col + j]));

}

}

}

}

template<class T>

void SparesMatrix<T>::Display() const

{

size_t arr_size = _array.size();

assert(arr_size != 0);

size_t index = 0;

for (size_t i = 0; i < _rowMatrix; i++)

{

for (size_t j = 0; j < _colMatrix; j++)

{

if (index < arr_size && _array[index]._row == i && _array[index]._col == j)

{

cout<<_array[index]._value<<" ";

index++;

}

else

{

cout<<_invalid<<" ";

}

}

cout<<endl;

}

cout<<endl;

}

// 转置 (列转置法)

template<class T>

SparesMatrix<T> SparesMatrix<T>::Transport()

{

size_t arr_size = _array.size();

assert(arr_size != 0);

SparesMatrix<T> ret;

ret._rowMatrix = _colMatrix;

ret._colMatrix = _rowMatrix;

ret._invalid = _invalid;

ret._array.reserve(arr_size); // 先开辟这么大的空间 提高效率 防止后面push_back()每次不够还要开辟

// 在原来的 行优先的 数组_array中,每次遍历一遍,找到这次列号与对应 的列j相等的元素 将这个元素行列互换 存入ret._array

// 相当于 将 原数组的 行优先 转化为 列优先

// 原数组的列优先 就相当于 转置后矩阵的 行优先

for (size_t j = 0; j < _colMatrix; j++)

{

size_t index = 0;

while (index < arr_size)

{

if (_array[index]._col == j)

{

//ret._array.push_back({_array[index]._col, _array[index]._row, _array[index]._value});

ret._array.push_back(Triple<T>(_array[index]._col, _array[index]._row, _array[index]._value));

}

index++;

}

if (arr_size == ret._array.size())

{

break;

}

}

return ret;

}

template<class T>

SparesMatrix<T> SparesMatrix<T>::FastTransport() // 快速转置

{

size_t arr_size = _array.size();

assert(arr_size > 0);

size_t index = 0;

SparesMatrix<T> ret;

ret._rowMatrix = _colMatrix;

ret._colMatrix = _rowMatrix;

ret._invalid = _invalid;

ret._array.resize(arr_size);// 调整大小 (不能用reserve(只是空间变大 但Size没变)  而resize 是调整大小 两个都变)

// 两张辅助表

// RowCounts 记录原矩阵 每列的 非零元素

// RowStart 记录原矩阵 列优先时 每列 首个非零元的 坐标

// 用这两张表 可以马上把 _array数组中的元素 定位到 ret._array(新表)中

int* RowCounts = new int[_colMatrix];

int* RowStart = new int[_colMatrix];

memset(RowCounts, 0, _colMatrix * sizeof(int));

memset(RowStart, 0, _colMatrix * sizeof(int));

// 初始化RowCounts

for (size_t i = 0; i < arr_size; i++)

{

RowCounts[_array[i]._col]++; //【好方法 统计可以用到】 由列号找到对应RowCounts

}

RowStart[0] = 0;

// 初始化 RowStart (由 RowCount 求出 RowStart)

for (size_t i = 1; i < _colMatrix; i++) // 注意i 从1开始

{

RowStart[i] = RowStart[i - 1] + RowCounts[i - 1];

}

// 根据RowStart 将原矩阵_array中的元素 一次 快速 的 对应到 ret.array

for (size_t i = 0; i< arr_size; i++)

{

//ret._array[RowStart[array[i]._col]++] = {_array[i]._col, _array[i]._row, _array[i]._value};

// RowStart[_array[i]._col]++ 更新下一个元素 在 ret._array中的 位置

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

}

delete[] RowCounts;

delete[] RowStart;

return ret;

}

void testSparseMatrix()

{

int array[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,},

};

SparesMatrix<int> s1((int*)array, 6, 5, 0);

s1.Display();

SparesMatrix<int> s2;

s2 = s1.Transport();

cout<<"转置后的矩阵为:"<<endl;

s2.Display();

SparesMatrix<int> s3;

s3 = s1.FastTransport();

cout<<"快速转置后的矩阵为:"<<endl;

s3.Display();

}

int main()

{

testSparseMatrix();

return 0;

}

时间: 2024-08-03 19:24:58

稀疏矩阵-压缩存储-列转置法- 一次定位快速转置法的相关文章

稀疏矩阵的列序递增法和一次定位快速转置法

稀疏矩阵:矩阵中大多数元素为0的矩阵,从直观上讲,当非零元素个数低于总元素的30%时,这样的矩阵为稀疏矩阵. 如: int array [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}}; 稀疏矩阵的压缩存储:使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放

稀疏矩阵压缩存储:CSR

Compressed Sparse Row,CSR格式的列下标向量和数据值向量与COO格式(三元组)类似,在行下标表示上做了压缩.根据数据的排列规则,只需要指定在哪个数据换到下一行就行. >>> col_idx = np.array([0,3,1,2,3,0,1,3]) >>> values = np.array([4,2,1,5,7,6,3,8]) >>> row_ptr = np.array([0,2,3,5,8]) >>> cs

稀疏矩阵的压缩存储与转置

稀疏矩阵:矩阵中大多数元素为0的矩阵(本文以行序为主序) 稀疏矩阵的三元组表述法: 类型结构: template <typename T> struct Triple { int _row; int _col; T _value; }; template <typename T> class SparseMatrix { public: SparseMatrix<T>::SparseMatrix(); SparseMatrix(const T* array, size_

稀疏矩阵的压缩存储和转置

1.稀疏矩阵:M*N的矩阵,矩阵中有效值的个数远小于无效值的个数,且这些数据的分布没有规律. 2.稀疏矩阵的压缩存储:压缩存储值存储极少数的有效数据. 由于非零元素分布没有任何规律,所以在进行压缩存储的时侯需要存储无效值的同时还要存储有效元素在矩阵中的位置,即有效元素所在的行号和列号,也就是在存储某个元素比如aij的值的同时,还需要存储该元素所在的行号i和它的列号j,这样就构成了一个三元组(i,j,aij)的线性表. 使用{ row, col, value }三元组存储每一个有效数据,三元组按原

数据结构进阶(二)矩阵(稀疏矩阵)的压缩存储

矩阵(稀疏矩阵)的压缩存储 注 本文转载地址: http://blog.163.com/zhoumhan_0351/blog/static/39954227201001112526244/ 为了节省存储空间并且加快处理速度,需要对这类矩阵进行压缩存储,压缩存储的原则是:不重复存储相同元素:不存储零值元素. 一.相关概念 ㈠特殊矩阵 矩阵中存在大多数值相同的元,或非0元,且在矩阵中的分布有一定规律. ⒈对称矩阵 矩阵中的元素满足 aij=aji    1≤i,j≤n ⒉三角矩阵 上(下)三角矩阵指

稀疏矩阵的压缩存储及转置

没有经过处理的稀疏矩阵其实就是一个特殊的二维数组,数组中的大部分元素是0或者其他类型的非法值,只有少数几个非零元素. 为了实现压缩存储,可以只存储稀疏矩阵的非0元素.在存储稀疏矩阵中的非0元素时,必须要存储该元素的行列号以及元素值.我们可以封装一个三元组类来存储这些元素. //三元组 template<class T> struct Triple { size_t _row;   //行 size_t _col;   //列 T _value;      //值 Triple<T>

C++实现稀疏矩阵的压缩存储、转置、快速转置

/*稀疏矩阵的压缩存储.转置.快速转置*/ #include <iostream> using namespace std; #include <vector> //三元组 template<class T> struct Triple { size_t _row; size_t _col; T _value; Triple(size_t row = 0, size_t col = 0, const T& value = T()) :_row(row) ,_co

稀疏矩阵的压缩存储及转置算法

矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合. 稀疏矩阵:有效数据远少于无效数据. eg:规定无效数据为 0 1 0 0 0 0 0 0 0 0 2 0 3 0 0 0 4 0 0 0 0 上述矩阵则可称为一个稀疏矩阵 我们在学习C语言的时候已经见过并使用过矩阵,其实它在我们的编程语言里可以翻译成二维数组,由于稀疏矩阵的有效数据十分的少,完全存储十分耗费我们的空间,所以我们选择只存储它的有效数据位,所以我们可以直接使用一维数组将其存储起来,但是我们必须让别人在看它时还能知道它是一个

稀疏矩阵的压缩存储及快速转置

当一个矩阵为稀疏矩阵时,有效数据的个数比无效数据要少得多,因此若将一个矩阵全部存储会浪费空间,可以只将有效数据存储起来,无效数据作为标记 代码如下: #include <iostream> #include <vector> using namespace std; //可用一个三元组来存储有效数据的信息 template<class T> struct Triple {  size_t _row;  size_t _col;  T _value; }; //系数矩阵类