特殊矩阵的压缩存储

本片博客讨论的特殊矩阵包括两部分:

(1)元素分布有特殊规律的矩阵,寻找规律对应的公式实现压缩存储。如:对称矩阵。

(2)非零元素很少的稀疏矩阵,可采用只存储非零元素的方式实现压缩存储。

首先呢,先来讨论下对称矩阵。

所谓对称矩阵呢,就是行和列相同,上矩阵和下矩阵对称。还是看图吧,一目了然。

看此矩阵,若要将其存储,会浪费空间。就对称这一特征来说,可只存储其上矩阵或者下矩阵。就以存储下矩阵为例。

在此程序中需要注意:

(1)若矩阵为N*N,则需要为其开辟N*(N+1)/2大的数组。

(2)矩阵i行j列的元素对应数组的下标为i*(i+1)/2+j的元素。

即:SymmetricMatrix[i][j] ==> Array[i*(i+1)/2+j]。

代码实现:

template <class T>
class SymmetricMatrix
{
public: //声明
	SymmetricMatrix(T* a,size_t size);
	~SymmetricMatrix();
	T& Access(size_t i,size_t j);
	void Display();
protected:
	T* _a;//数组
	size_t _size;//压缩矩阵的下标
	size_t _n;//方阵的行,列
};

//函数实现

template <class T>
SymmetricMatrix<T>::SymmetricMatrix(T* a,size_t size)
                 :_a(new T[size*(size+1)/2])//为_a开辟空间
		 ,_size(size*(size+1)/2)//下标
		 ,_n(size)//行,列
{
	size_t _index = 0;
	for(size_t i=0;i<_n;i++)
	{
		for(size_t j=0;j<_n;j++)
		{
			if(i>=j)
			{
				_a[_index++] = a[i*_n+j];//下矩阵 
			}
			else//上矩阵不存储
				break;
		}
	}
}

template <class T>
SymmetricMatrix<T>::~SymmetricMatrix()
{
	if(_a != NULL)
	{
		delete[] _a;
		_a = NULL;
		_size = 0;
	}
}

template <class T>
T& SymmetricMatrix<T>::Access(size_t i, size_t j)//(i,j)位置上的元素
{
	if(i<j)//上矩阵
	{
		swap(i,j);//对称,交换
	}
	return _a[i*(i+1)/2+j];
}

template <class T>
void SymmetricMatrix<T>::Display()//打印对称矩阵
{
	for(size_t i=0;i<_n;i++)
	{
		for(size_t j=0;j<_n;j++)
		{
			if(i>=j)//下矩阵
			{
				cout<<_a[i*(i+1)/2+j]<<" ";
			}
			else//上矩阵
			{
				cout<<_a[j*(j+1)/2+i]<<" ";
			}
		}
		cout<<endl;
	}
	cout<<endl;
}

测试函数:

void Test()
{
	int arr[][4]={{0,1,2,3},
	              {1,0,4,5},
	              {2,4,0,6},
	              {3,5,6,0}};
	SymmetricMatrix<int> sm((int*)arr,4);
	sm.Display();
	int ret = sm.Access(2,3);
	cout<<ret<<endl;
	return 0;
}

测试结果:

接下来呢,我们看一下稀疏矩阵。

所谓系数矩阵呢,就是指矩阵中的大多数元素为0。当非零元素的个数低于总元素的30%时,这样的矩阵称为稀疏矩阵。如下所示:

如何存储稀疏矩阵呀,对于稀疏矩阵的存储,采取只存储非零元素的方法。由于稀疏矩阵的元素并没有规律,所以在存储元素时,还必须存储非零元素的行号和列号。这就是稀疏矩阵的三元组表示法。

三元组的结构:

template <class T>
struct Triple
{
	Triple(const T& value = T(),size_t row = 0,size_t col = 0)//初始化
		:_value(value)
		,_row(row)
		,_col(col)
	{}
	T _value; //值
	size_t _row;//行
	size_t _col;//列
}

代码实现:

template <class T>
class SpareMatrix//稀疏矩阵
{
public:
	SpareMatrix();//无参构造函数
	SpareMatrix(T* a,size_t m,size_t n,const T& invalue);//有参构造函数
	void Display();//打印
	SpareMatrix<T> Transport();//转置
	SpareMatrix<T> FastTransport();//快速转置
protected:
	vector<Triple<T> > _a;//存储三元组的数组
	size_t _rowSize;//行
	size_t _colSize;//列
	T _invalue;//非法值
};

template <class T>
SpareMatrix<T>::SpareMatrix(T *a, size_t m, size_t n, const T& invalue)
                :_rowSize(m)
		,_colSize(n)
		,_invalue(invalue)
{
	for(size_t i=0;i<m;i++)
	{
		for(size_t j=0;j<n;j++)
		{
			if(a[i*n+j] != invalue)
			{
				_a.push_back(Triple<T>(a[i*n+j],i,j));
			}
		}
	}
}
template <class T>
SpareMatrix<T>::SpareMatrix()
:_rowSize(0)
,_colSize(0)
{}
template <class T>
void SpareMatrix<T>::Display()
{
	size_t index = 0;
	for(size_t i=0;i<_rowSize;i++)
	{
		for(size_t j=0;j<_colSize;j++)
		{
			if(index<_a.size()&&(_a[index]._row == i)&&(_a[index]._col == j))
			{
				cout<<_a[index]._value<<" ";
				++index;
			}
			else
			{
				cout<<_invalue<<" ";
			}
		}
		cout<<endl;
	}
	cout<<endl;
}

template <class T>
SpareMatrix<T> SpareMatrix<T>::Transport()//从三元数组上入手,以列为主,重新存储
{
	SpareMatrix<T> tmp;
	tmp._rowSize = _colSize;//行
	tmp._colSize = _rowSize;//列
	tmp._invalue = _invalue;

	Triple<T> t;
	for(size_t i=0;i<_colSize;i++)
	{
		size_t index = 0;
		while(index < _a.size())
		{
			if(_a[index]._col == i)
			{
				t._row = _a[index]._col;//交换行号,列号
				t._col = _a[index]._row;
				t._value = _a[index]._value;
				tmp._a.push_back(t);
			}
			++index;
		}
	}
	return tmp;
}

template <class T>
SpareMatrix<T> SpareMatrix<T>::FastTransport()//快速逆置
{
	SpareMatrix<T> tmp;
	tmp._rowSize = _colSize;//行
	tmp._colSize = _rowSize;//列
	tmp._invalue = _invalue;

	SpareMatrix<T> rowCount = new int[tmp._rowSize];//记录每一列元素的个数
	SpareMatrix<T> rowStart = new int[tmp._rowSize];//记录元素在数组上开始的位置
	memset(rowCount,0,sizeof(int)*tmp._rowSize);//初始化为0
	memset(rowStart,0,sizeof(int)*tmp._rowSize);

	size_t index = 0;
	while(index < _a.size())//统计每一列上的元素个数
	{
		rowCount[_a[index]._col]++;
		++index;
	}

	index = 0;
	rowStart[0] = 0;
	for(size_t i=1;i<_colSize;i++)//每个元素在数组中开始的位置
	{
		rowSize[i] = rowSize[i-1] + rowCount[i-1];
	}

	index = 0;
	tmp._a.resize(_a.size());//开辟空间并默认为0
	while(index < _a.size())
	{
		size_t rowIndex = _a[index]._col
		int& start = rowStart[rowIndex];

		Triple<T> t;
		t._value = _value;
		t._row = col;
		t._col = _row;

		tmp._a[start++] = t;
	}
	return tmp;
}

//测试函数:
void Test()
{
	int arr[4][5] = {{0,1,0,0,0},
	                 {0,0,0,2,0},
	                 {0,4,0,0,0},
	                 {0,0,3,0,0}};
	SpareMatrix<int> sm((int*)arr,4,5,int());
	sm.Display();
	//sm.Transport((int*)arr,4,5,int());
	//sm.Display(5,4);
	SpareMatrix<int> ret = sm.Transport();
	ret.Display();

	SpareMatrix<int> ret1 = sm.FastTransport();
	ret1.Display();

	return 0;
}

测试结果:

时间: 2024-10-16 17:16:20

特殊矩阵的压缩存储的相关文章

特殊矩阵的压缩存储(转自chunlanse2014)

对称矩阵 对于一个矩阵结构显然用一个二维数组来表示是非常恰当的,但在有些情况下,比如常见的一些特殊矩阵,如三角矩阵.对称矩阵.带状矩阵.稀疏矩阵等,从节约存储空间的角度考虑,这种存储是不太合适的.下面从这一角度来考虑这些特殊矩阵的存储方法. 对称矩阵的特点是:在一个n 阶方阵中,有aij=aji ,其中1≤i , j≤n,如图5.5 所示是一个5阶对称矩阵.对称矩阵关于主对角线对称,因此只需存储上三角或下三角部分即可,比如,我们只存储下三角中的元素aij,其特点是j≤i 且1≤i≤n,对于上三角

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

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

对称矩阵的压缩存储和输出

矩阵我个人理解就是一堆数据放在一块儿排列整齐,当然正规一点说就是m行n列的数据构成.在编程中一般采用数组对其进行存储,但矩阵中的某些特殊矩阵里,有时会出现很多数据相等或者存有很多0只有某几个位置为别的数据,那么这类矩阵我们在用数组存储的时候就会感觉比较的浪费空间,那么会对一些特殊矩阵进行压缩存储. 常见的能够压缩存储的矩阵有对称矩阵和稀疏矩阵,今天主要说说对称矩阵的压缩存储.先来说说什么是对称矩阵,相信大家都很熟悉,对于一个矩阵如果它的行和列相等并且矩阵中的数据是关于对角线对称的,那么我们称这样

矩阵-----对称矩阵及其压缩存储&&稀疏矩阵

什么是对称矩阵(SymmetricMatrix)? 对称对称-------看 设一个N*N的方阵A,A中任意元素Aij,当且仅当Aij == Aji(0 <= i <= N-1 && 0 <= j <= N-1),则矩阵A是对称矩阵.以矩阵的对角线为分隔,分为上三角和下三角. 压缩存就是矩阵存储时只需要存储上三角/下三角的数据,所以最多存储n(n+1)/2个数据. 对称矩阵和压缩存储的对应关系:下三角存储i>=j,  SymmetricMatrix[i][j]

矩阵压缩存储之三元组顺序表

形态: 实现: /***************************************** 稀疏矩阵的三元组顺序表存储表示 by Rowandjj 2014/5/3 ******************************************/ #include<IOSTREAM> using namespace std; #define MAXSIZE 12500//非零元个数的最大值 typedef int ElemType; typedef struct _DATA_

c++对称矩阵的压缩存储

对称矩阵 对称矩阵及对称矩阵的压缩存储 设一个N*N的方阵A,A中任意元素Aij,当且仅当Aij == Aji(0 <= i <= N-1 && 0 <= j <= N-1),则矩阵A是对称矩阵. 以矩阵的对角线为分隔,分为上三 角和下三角. 压缩存储称矩阵存储时只需要存储上三角/下三角的数据,所以最多存 储n(n+1)/2个数据. 对称矩阵和压缩存储的对应关系: 下三角存储i>=j, SymmetricMatrix[i][j] == Array[i*(i+1

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}//行 列 值三元组存储每一个有效 数据,三元组按原矩阵中的位置,以行优先级

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

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

稀疏矩阵的压缩存储

    压缩存储值存储极少数的有效数据.使用{row,col,value}三元组存储每一个有效数据,三元组按原矩阵中的位置,以行优先级先后顺序依次存放. #define _CRT_SECURE_NO_WARNINGS 1 #include <vector> #include<iostream> using namespace std; //三元组的定义 template<class T> struct Triple { T _value; size_t _row; si