数据结构八:稀疏矩阵(涉及三元组,十字链表)

###1. 稀疏矩阵的定义
稀疏矩阵是零元素居多的矩阵,稀疏矩阵和稠密矩阵之间并没有一个精确的界限。假设m行n列的矩阵含有t个非零元素,一般称 δ = t m n \delta = \dfrac{t}{mn} 为稀疏因子。一般认为 δ 0.05 \delta \le 0.05 的矩阵为稀疏矩阵。
稀疏矩阵常用的存储方式是通过三元组来进行存储。也就是对于每个非零元素,用三元组(行号,列号,值)来表示。接下来可以使用顺序表或者链表的方式来存储这些三元组,具体实现如下:
实现的时候主要注意设置指定位置(r, c)的元素值v时,应该首先查找是否在三元组中有指定的三元组。如果存在,当v=0时,则删除此三元组;否则,修改三元组的的非零元素值。如果不存在指定位置的三元组,当v = 0时不做任何操作,否则插入三元组。

#pragma once
#define DEFAULT_ROWS 10
#define DEFAULT_COLS 10
#define DEFAULT_SIZE 10
//三元组类
template<typename elemType>
struct Triple
{
	//数据成员
	int rows, cols;
	elemType value;

	//
	Triple();//无参构造函数
	Triple(int rs, int cs, elemType v)
	{
		rows = rs; cols = cs; value = v;
	}
};


//稀疏矩阵三元组顺序表类
template<typename elemType>
class TriSparseMatirx
{
protected:
	//数据成员
	Triple<elemType>* elems;
	int maxSize; //非零元素的最大个数
	int rows, cols, num;//稀疏矩阵的行数列数以及已存入的非零元素的个数

public:
	TriSparseMatirx(int rs = DEFAULT_ROWS, int cs = DEFAULT_COLS,
		int size = DEFAULT_SIZE);
	~TriSparseMatirx();
	int getRows() const;//返回稀疏矩阵的行数
	int getCols() const;//返回稀疏矩阵的列数
	int getNum() const;//返回稀疏矩阵非零元素的个数
	bool setElem(int r, int c, const elemType& v);//设置指定位置的元素
	bool getElem(int r, int c, elemType& v);//获取指定位置的元素的值

	TriSparseMatirx(const TriSparseMatirx<elemType>& copy);
	TriSparseMatirx<elemType>& operator=(const TriSparseMatirx<elemType>& copy);
};


template<typename elemType>
TriSparseMatirx<elemType>::TriSparseMatirx(int rs , int cs ,int size )
{
	//这个地方加一下对rs,cs的判断
	rows = rs;
	cols = cs;
	maxSize = size;
	num = 0;
	elems = new Triple<elemType>[maxSize];
}

template<typename elemType>
TriSparseMatirx<elemType>::~TriSparseMatirx()
{
	if (elems != NULL) delete []elems;
}

template<typename elemType>
int TriSparseMatirx<elemType>::getRows() const
{
	return rows;
}


template<typename elemType>
int TriSparseMatirx<elemType>::getCols() const
{
	return cols;
}


template<typename elemType>
int TriSparseMatirx<elemType>::getNum() const
{
	return num;
}


template<typename elemType>
bool TriSparseMatirx<elemType>::setElem(int r, int c, const elemType& v)
{
	if (r<1 || r>rows || c<1 || c>cols)
	{
		return false;
	}

	int i, j;
	for (j = num - 1; j >= 0 && r < elems[j].rows || r == elems[j].rows
		&& c < elems[j].cols; j--);//查找三元组位置

	if (j>=0 && elems[j].rows == r || elems[j].cols == c)
	{ //找到三元组
		if (v == 0)
		{  //删除三元组
			for (i = j + 1; i < num;i++)
			{
				elems[i - 1] = elems[i];
			}
			num--;
		}
		else
		{
			elems[j].value = v;
		}
		return true;
	}
	else if(v != 0)//如果没有找到且v不为0则插入
	{
		if (num < maxSize)
		{//将三元组插入到三元组表中
			for (i = num - 1; i > j;i--)
			{
				elems[i + 1] = elems[i]
			}
			//j+1为空的位置插入元素
			elems[j + 1], rows = r;
			elems[j + 1].cols = c;
			elems[j + 1].value = v;
			num++;
			return true;
		}
		else
		{
			return false;
		}
	}
}


template<typename elemType>
bool TriSparseMatirx<elemType>::getElem(int r, int c, elemType& v)
{
	if (r<1 || r>rows || c<1 || c>cols)
	{
		return false;
	}

	int i, j;
	for (j = num - 1; j >= 0 && r < elems[j].rows || r == elems[j].rows
		&& c < elems[j].cols; j--);//查找三元组位置

	if (j >= 0 && elems[j].rows == r || elems[j].cols == c)
	{
		v = elems[j].value;
		return true;
	}
	else
	{
		return false;
	}
}


template<typename elemType>
TriSparseMatirx<elemType>::TriSparseMatirx(const TriSparseMatirx<elemType>& copy)
{
	maxSize = copy.maxSize;
	elems = new Triple<elemType>[maxSize];
	num = copy.num
		for (int i = 0; i < num;i++)
	{
		elems[i] = copy.elems[i];
	}
}

template<typename elemType>
TriSparseMatirx<elemType>& TriSparseMatirx<elemType>::operator=(const TriSparseMatirx<elemType>& copy)
{
	if (&copy != this)
	{
		maxSize = copy.maxSize;
		elems = new Triple<elemType>[maxSize];
		num = copy.num
			for (int i = 0; i < num; i++)
			{
				elems[i] = copy.elems[i];
			}
	}

	return *this;
}

2矩阵的转置

如果矩阵是用二维数组表示的,则转置操作很简单。转置操作主要是将每个元素的行号和列号互换。由于在三元组表中,元素按行号或者列号排列,所以在行号或列号交换之后,还要调整元素的位置,使其仍按行序或列序进行排列。转置的具体步骤如下:
(1)将每个非零元素对应的三元组的行号和列号进行互换。
(2)对三元组重新排序,使其中的元素按行序或者列序排列。
如果要降低算法的时间复杂度,这时可以开辟一个新的三元组表,假设原三元组表为source,转置后的三元组为dest,具体步骤如下:
(1)将三元组表source中的每个元素取出交换其行号和列号。
(2)将变换后的三元组存入目标dest三元组表中适当位置,使dest中的元素按照行序或者列序进行排列。

猜你喜欢

转载自blog.csdn.net/wuye999/article/details/79629157