您的位置:首页 > 理论基础 > 数据结构算法

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

2018-03-20 17:40 417 查看

1. 稀疏矩阵的定义

稀疏矩阵是零元素居多的矩阵,稀疏矩阵和稠密矩阵之间并没有一个精确的界限。假设m行n列的矩阵含有t个非零元素,一般称δ=tmnδ=tmn为稀疏因子。一般认为δ≤0.05δ≤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 (© != 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中的元素按照行序或者列序进行排列。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构 矩阵