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

没有经过处理的稀疏矩阵其实就是一个特殊的二维数组,数组中的大部分元素是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;
}

附完整代码:

/********************************************************************/
/*
   实现稀疏矩阵的压缩存储
   实现稀疏矩阵的三元组
   利用容器存储三元组
   实现稀疏矩阵的列序转置和快速转置
   打印稀疏矩阵
                                       By:Lynn-Zhang
*/
/********************************************************************/

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<vector>
#include<assert.h>
using namespace std;

#define ROW 6
#define COL 5

//三元组
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)
	{}
};

template<class T>
class SparseMatrix
{
public:
	SparseMatrix();  // 声明无参的构造函数
	SparseMatrix(const T* array, size_t row, size_t col, const T& invalid); //构造函数初始化
	SparseMatrix<T> Transport();   //转置
	SparseMatrix<T> FastTranaport(); //快速转置
	void Display(); //打印

protected:
	vector<Triple<T>> _array;      //利用容器压缩存储稀疏矩阵
	size_t _rowMatrix;       // 稀疏矩阵行数
	size_t _colMatrix;         // 稀疏矩阵列数
	T _invalid;                  // 定义非法值
};

template<class T>   //无参的构造函数
SparseMatrix<T>::SparseMatrix()
{}

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);
			}
		}
	}
}

template<class T>  //打印
void SparseMatrix<T>::Display() //打印
{
	assert(_array.size()!=0);
	size_t index = 0;
	for (size_t i = 0; i < _rowMatrix; i++)
	{
		for (size_t j = 0; j < _colMatrix; ++j)
		{
			if (index < _array.size() && _array[index]._row == i&&_array[index]._col == j)
			{
				cout << _array[index]._value << " ";
				index++;
			}
			else
			{
				cout << ‘0‘ << " ";
			}
		}
		cout << endl;
	}
	cout << endl<<endl;
}

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;
}

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;
}

int main()
{
	int array[ROW][COL] =
	{
			{ 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> sm((int*)array, ROW, COL, 0);
	sm.Display();

	SparseMatrix<int> sm1;
	sm1 = sm.Transport();
	cout << "转置后的矩阵为: " << endl << endl;
	sm1.Display();

	SparseMatrix<int> sm2;
	sm2 = sm.FastTranaport();
	cout << "快速转置后的矩阵为: " << endl << endl;
	sm2.Display();

	system("pause");
	return 0;
}

时间: 2024-10-08 23:19:19

稀疏矩阵的压缩存储及转置的相关文章

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

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

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

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

稀疏矩阵:矩阵中大多数元素为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_

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

矩阵(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> template <class T> struct Triple { T _value; size_t _row; size_t _col; Triple(const T& t =T(),size_t row = 0 ,size_t col = 0) :_value(t) , _row(row) , _col(col) {} }; template <class T> class

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

SparseMatrix.hpp #pragma once #include<iostream> using namespace std; #include<vector> template<class T> struct Triple{  T _value;  size_t _row;  size_t _col; }; #define ROW 6 #define COL 5 template<class T> class SparseMatrix{ pub

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

稀疏矩阵的压缩存储 压缩存储值存储极少数的有效数据.使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放. 压缩存储:行优先一行一行扫 有效数据存入以为矩阵_arr 列转置法 : 从前向后遍历压缩矩阵,先找列号为0的存入 转置矩阵的压缩矩阵.然后从前向后找列号为1的 ...直到转置矩阵的压缩矩阵大小和 原矩阵的一样大 这时就找完了 时间复杂度为    O(原矩阵列数 * 压缩矩阵长度) 一次定位快速转置法: 设置两个辅助矩阵 RowCou

对称矩阵、稀疏矩阵的压缩存储

1)对称矩阵的压缩存储 对称矩阵顾名思义就是符合行和列的个数相同,并且矩阵中存储的数据上三角和下三角中对应位置上的元素值是相等的.为了能够减少存储的空间,我们可以只存储上三角矩阵.或者下三角矩阵中的元素,这样就能够极大地节省空间的浪费.下面是对称矩阵的示列: 假设对称矩阵为n*n,这里以行优先存储下三角矩阵,总共需要存储的元素有n*(n+1)/2个元素,从而将n*n个元素压缩到n*(n+1)/2大小的空间中. 下面是具体的程序实现: --symmetric.h文件 //实现对称矩阵 #inclu

c++稀疏矩阵的压缩存储

稀疏矩阵 M*N的矩阵 其中有效值的个数远小于无效值的个数 且分布没有规律 Eg: int array [6][5] =     {{1, 0, 3, 0, 5}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {2, 0, 4, 0, 6}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}; 稀疏矩阵的压缩存储 压缩存储值存储极少数的有效数据.使用{row,col,value}//行 列 值三元组存储每一个有效 数据,三元组按原矩阵中的位置,以行优先级