经典数据结构之稀疏矩阵

数据的存储形式,不外乎链表和类数组两种。使用二维数组存储矩阵,如果该矩阵是稀疏的,那么会浪费很多空间。例如一个4*4的对角阵,很明显,只有主对角线上才有元素。那么使用二维数组存储需要16个单位的 存储空间。然而通过定义一个结构体:

template<typename T>
struct SDataType{
    friend class CSparseMatrix<T>;
    int m_nRow;
    int m_nCol;
    T m_nVal;
};

然后将其存放于数组,所需要的空间则为[(sizeof(T) +2*sizeof(int))* 4]相对于[sizeof(T) * 16]来说,会节约很多空间。故我们通常使用这种方式存储稀疏矩阵。然而矩阵的存储,可以是基于行的,或者是基于列的。下面以基于行来示例代码:

.h文件

#ifndef CSPARSEMATRIX_HHH
#define CAPARSEMATRIX_HHH

#include <iostream>
#include <cassert>
template<typename T>
class CSparseMatrix;

template<typename T>
struct SDataType{
    friend class CSparseMatrix<T>;
    int m_nRow;
	int m_nCol;
	T m_nVal;
};

template <typename T>
class CSparseMatrix{
private:
	// members;
	SDataType<T>* m_pArray;
	int m_nLength;
	int m_nMaxSize;
	int m_nRows;
	int m_nCols;

public:
	// constructors;
	CSparseMatrix(const int& maxSize);
	~CSparseMatrix();
	// methods;
	friend std::ostream& operator<< (std::ostream& out, const CSparseMatrix<T>& matrix){
		out << "rows = " << matrix.m_nRows << " columns = " << matrix.m_nCols << std::endl;
		out << "length = " << matrix.m_nLength << std::endl;
		out << "row" << '\t' << "col" << '\t' <<  "val" << std::endl;
		for(int i = 0; i < matrix.m_nLength; i ++)
			out << matrix.m_pArray[i].m_nRow << '\t' << matrix.m_pArray[i].m_nCol << '\t' << matrix.m_pArray[i].m_nVal << std::endl;
		return out;
	}
	friend std::istream& operator>> (std::istream& in, CSparseMatrix<T>& matrix){
		std::cout << "number of rows, columns, length" << std::endl;
		in >> matrix.m_nRows >> matrix.m_nCols >> matrix.m_nLength;
		assert(matrix.m_nLength <= matrix.m_nMaxSize);
		for(int i = 0; i < matrix.m_nLength; i ++){
			std::cout << "row number, column number, value" << std::endl;
			in >> matrix.m_pArray[i].m_nRow >> matrix.m_pArray[i].m_nCol >> matrix.m_pArray[i].m_nVal;
		}
		return in;
	}
    // append;
	void mAdd(const CSparseMatrix<T>& aMatrix, CSparseMatrix<T>& bMatrix);
	void mTranpose(CSparseMatrix<T>& aMatrix);
private:
    void mAppend(const SDataType<T>& data);
};

template<typename T>
CSparseMatrix<T>::CSparseMatrix(const int& maxSize = 10):
    m_nMaxSize(maxSize){
    assert(m_nMaxSize > 0);
	m_nLength = m_nCols = m_nRows = 0;
	m_pArray = new SDataType<T>[m_nMaxSize];
}

template<typename T>
CSparseMatrix<T>::~CSparseMatrix(){
	delete [] m_pArray;
}

template<typename T>
void CSparseMatrix<T>::mAppend(const SDataType<T>& data){
	if(m_nLength >= m_nMaxSize)
		printf("the matrix is full, cannot append any more\n");
	else{
        m_pArray[m_nLength] = data;
		m_nLength ++;
	}
}	

template<typename T>
void CSparseMatrix<T>::mAdd(const CSparseMatrix<T>& aMatrix, CSparseMatrix<T>& bMatrix){
    if(aMatrix.m_nRows != m_nRows || aMatrix.m_nCols != m_nCols)
		printf("the matrix is not compatable\n");

	bMatrix.m_nCols = m_nCols;
	bMatrix.m_nRows = m_nRows;
	bMatrix.m_nLength = 0;
    
	int i = 0;    // indicator of self;
	int j = 0;    // indicator of aMatrix;
    while(i < m_nLength && j < aMatrix.m_nLength){
		if(bMatrix.m_nLength == bMatrix.m_nMaxSize){
			printf("Not enough size to add");
			return;
		}

		int ipos = m_pArray[i].m_nRow * m_pArray[i].m_nCol + m_pArray[i].m_nCol;
		int jpos = aMatrix.m_pArray[j].m_nRow * aMatrix.m_pArray[j].m_nCol  + aMatrix.m_pArray[j].m_nCol;
        if(ipos < jpos){
			bMatrix.mAppend(m_pArray[i]);
			i ++;
		}else if(ipos > jpos){
			bMatrix.mAppend(aMatrix.m_pArray[j]);
			j ++;
		}else{
			SDataType<T> data;
			data.m_nVal = m_pArray[i].m_nVal + aMatrix.m_pArray[j].m_nVal;
			data.m_nRow = m_pArray[i].m_nRow;
			data.m_nCol = m_pArray[i].m_nCol;
			bMatrix.mAppend(data);
			i ++;
			j ++;
		}
		bMatrix.m_nLength ++;
	}
	while(i < m_nLength){
		if(bMatrix.m_nLength == bMatrix.m_nMaxSize){
			printf("Not enough size to add");
			return;
		}

		bMatrix.mAppend(m_pArray[i]);
		i ++;
	}
	while(j < bMatrix.m_nLength){
		if(bMatrix.m_nLength == bMatrix.m_nMaxSize){
			printf("Not enough size to add");
			return;
		}
	    bMatrix.m_pArray[j];
		j ++;
	}
}

template<typename T>
void CSparseMatrix<T>::mTranpose(CSparseMatrix<T>& matrix){
	if(m_nLength > matrix.m_nMaxSize){
		printf("Not enough mem\n");
		return;
	}
    matrix.m_nCols = m_nRows;
	matrix.m_nRows = m_nCols;
    matrix.m_nLength = m_nLength;

    int* numberInCol = new int[m_nCols + 1];
	int* nextOrderByRow = new int[m_nRows + 1];

	// initialize
	for(int i = 0; i < m_nCols; i ++)
		numberInCol[i] = 0;

	nextOrderByRow[1] = 0;
	nextOrderByRow[0] = 0;

	for(int i = 1; i <= m_nLength; i ++)
		numberInCol[m_pArray[i].m_nCol] ++;
	for(int j = 2; j <= m_nCols; j ++) // row start;
		nextOrderByRow[j] = nextOrderByRow[j - 1] + numberInCol[j - 1];
    
    for(int i = 0; i < m_nLength; i ++){
		int pos = nextOrderByRow[m_pArray[i].m_nCol] ++;
		matrix.m_pArray[pos].m_nRow = m_pArray[i].m_nCol;
		matrix.m_pArray[pos].m_nCol = m_pArray[i].m_nRow;
		matrix.m_pArray[pos].m_nVal = m_pArray[i].m_nVal;
	}
}
#endif





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值