稀疏矩陣的壓縮存儲及轉置

沒有經過處理的稀疏矩陣其實就是一個特殊的二維數組,數組中的大部分元素是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];

列號01234
RowCounts[col]20202
RowStart[col]02244
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;
}

wKiom1cRDD6B4qizAAAnq-ygG7I404.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章