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

矩陣(Matrix)是一個按照長方陣列排列的複數實數集合.編程

稀疏矩陣:有效數據遠少於無效數據。
數組

 eg:規定無效數據爲 0 編程語言

    1 0 0 0 0ide

    0 0 0 0 2學習

    0 3 0 0 0spa

    4 0 0 0 0翻譯

上述矩陣則可稱爲一個稀疏矩陣orm

咱們在學習C語言的時候已經見過並使用過矩陣,其實它在咱們的編程語言裏能夠翻譯成二維數組,因爲稀疏矩陣的有效數據十分的少,徹底存儲十分耗費咱們的空間,因此咱們選擇只存儲它的有效數據位,因此咱們能夠直接使用一維數組將其存儲起來,可是咱們必須讓別人在看它時還能知道它是一個矩陣,因而咱們必須將其所在的位置使用一個三元組存儲起來!htm

三元組的定義以下:ip

template<class T>
struct Triple
{
	T _value;//有效值
	int _row;//該值所在行
	int _col;//該值所在列
	Triple(const T& data = T(), int m = 0, int n = 0)
	       :_value(data),_row(m), _col(n)
	{}
};


矩陣的定義以下:

class SpaMatrix
{
public:
	SpaMatrix(T* arr = NULL, int m = 0, int n = 0, int inva = 0)
		:_Row(m), _Col(n), _invalid(inva)
	{
		int index = 0;
		for (int i = 0; i < m; i++)
		{
			for (int j = 0; j < n; j++)
			{
				if (arr[i*n + j] != _invalid)
				{
					_a.push_back(Triple<T>(arr[i*n + j], i, j));
					_n ++;
				}
			}
		}
	}
private:
	vector< Triple<T> > _a;//存儲三元組
	int _invalid;//規定的無效值
	int _Row;//矩陣的行數
	int _Col;//矩陣的列數
};


在矩陣裏,咱們常常可以看見一個運算,就是矩陣的轉置,即便得a[i][j] = a[j][i],咱們以前在存儲矩陣時選擇了行優先的存儲方式,可是,轉置以後,咱們的矩陣是以原來的行爲它的列,咱們該如何作呢?

方法一:普通轉置

**咱們遍歷矩陣,將第一列數據先放入新的矩陣,再放第二列,第三列,以此類推,這樣,咱們就可以獲得新的矩陣

下面是代碼的實例(截取重要部分代碼):

	//普通轉置
	SpaMatrix<T>::SpaMatrix<T> OrdinaryTrans()
	{
		int count = 0;
		int index = 0;
		SpaMatrix<T> sp;//使用一個臨時變量存儲轉置後的矩陣
		
			for (int j = 0; j < _Col; j++)
			{ 
				for (int index = 0; index < _a.size(); index++)
				{
					if (_a[index]._col == j)
					{
					    //每次只push須要的列
						sp._a.push_back(_a[index]);
						sp._a[index]._row = _a[index]._col;
						sp._a[index]._col = _a[index]._row;
					}
				}
			}
			//更新轉置後的矩陣行列信息
			sp._Row = _Col;
			sp._Col = _Row;
			
		return sp;
	}


方法二:快速轉置

**咱們將原來的矩陣的每一列有效數據的起始位和每一列有效數據的個數保存起來,做爲新矩陣的每一行有效數據的起始位置和有效數據個數,當咱們想要的獲得某個數據時,使用 上一行的起始位置+有效數據的個數便可獲得咱們新的矩陣。

咱們來看看代碼的實例:

	//快速轉置
	SpaMatrix<T>::SpaMatrix<T> FastTrans()
	{
		//統計有效數據的開始位置
		int *RowStart = new int[_Col];
		//統計轉置以後的矩陣裏每行的有效數據的個數
		int *RowCount = new int[_Col];
		memset(RowCount, 0, sizeof(int)*_Col);
		memset(RowStart, 0, sizeof(int)*_Col);
		size_t index = 0;

		//Set RowCount
		while (index < _a.size())
		{
			RowCount[_a[index]._col]++;
			index++;
		}
				
		//Set RowStart
		RowStart[0] = 0;
		for (int i = 1; i < _Col; i++)
		{
			RowStart[i] = RowStart[i - 1] + RowCount[i - 1];
		}

		//構造轉置以後的矩陣
		SpaMatrix<T> sptrans;
		sptrans._Row = _Col;
		sptrans._Col = _Row;
		sptrans._n = _n;
		
		//index 值已經改變了,必須從新讓其等於0
		index = 0;

		//此處使用下標訪問必須開闢空間,但若是使用push_back()能夠不用開闢~
		sptrans._a.resize(_a.size());
	        while(index < _a.size())
		{
			int Rowindex = _a[index]._col;
			//此處注意引用
			int& RowSt = RowStart[Rowindex];

			sptrans._a[RowSt]._value = _a[index]._value;
			sptrans._a[RowSt]._col = _a[index]._row;
			sptrans._a[RowSt]._row = _a[index]._col;

			index++;
			//每次必須更新該位置,不然錯誤
			RowSt++;
		}
		return sptrans;
	}

以上是我本身實現的轉置代碼,雖然代碼渣,可是就是有迷之自信敢給大家看,我就問大家怕不怕B_0037.gif

相關文章
相關標籤/搜索