您的位置:首页 > 其它

通过三元组用顺序存储方式封装稀疏矩阵

2006-06-09 17:11 387 查看
前两天学了稀疏矩阵的存储方法和一些操作,今天自己将其封装成一个类与大家分享一下(水平有限,如果有什么缺点,请各位大虾多多批评指正)

头文件:
struct Item //存放非零元信息的结构
{
int row,col;
float data;
};

class CMartixA
{
public:
void AddVal(int row,int col,float data); //矩阵加上一个数
void Multiply(CMartixA ma,CMartixA& result); //矩阵相乘
void Add(CMartixA ma,CMartixA& result); //矩阵相加
void Transpose(CMartixA ma); //求转置矩阵
void Clear(); //矩阵清零
void ReSetRPos(); //计算rpos(每行第一个非零元素所对应的m_val位置
void Print(float result[][Max]); //将矩阵输出到二维数组result
void SetVal(int row,int col,float data); //如果data是非零元,则插入或修改
int GetCol(); //返回列数
int GetRow(); //返回行数
int GetNum(); //返回非零元个数
void SetCol(int col); //设置列数
void SetRow(int row); //设置行数
CMartixA();//构造函数
virtual ~CMartixA();//析构函数

struct Item m_val[Max]; //存放三元组数组
int rpos[Max]; //存放每行第一个非零元在数组中的位置
protected:
int m_row,m_col,m_num; //行数,列数,非零元个数
};

cpp文件:
CMartixA::CMartixA()
{
m_num = 0;
m_col = 0;
m_row = 0;
for(int i = 0;i<Max;i++)
rpos[i] = 0;
}

CMartixA::~CMartixA()
{

}

void CMartixA::SetRow(int row)
{
m_row = row;
}

void CMartixA::SetCol(int col)
{
m_col = col;
}

int CMartixA::GetNum()
{
return m_num;
}

int CMartixA::GetRow()
{
return m_row;
}

int CMartixA::GetCol()
{
return m_col;
}

void CMartixA::SetVal(int row, int col, float data)
{
//如果data是非零元,则插入或修改
if(data != 0) //data不为零,操作
{
int i,k;
if(m_num == 0)
{
m_val[m_num].row = row;
m_val[m_num].col = col;
m_val[m_num].data = data; //如果row行col列不存在非零元,则插入
m_num++;
rpos[row]++;
}
else
{
for(i = 0;i<m_num;i++)
{
if(m_val[i].row > row)
{
for(k = m_num;k>i;k--)
m_val[k] = m_val[k-1];
m_val[i].data = data; //如果row行col列不存在非零元,则插入
m_val[i].col = col;
m_val[i].row = row;
m_num++;
ReSetRPos();
break;
}
if(m_val[i].row == row)
{
if(m_val[i].col > col)
{
for(k = m_num;k>i;k--)
m_val[k] = m_val[k-1];
m_val[i].data = data; //如果row行col列不存在非零元,则插入
m_val[i].col = col;
m_val[i].row = row;
m_num++;
ReSetRPos();
break;
}
if(m_val[i].col == col)
{
m_val[i].data = data; //如果row行col列已经存在非零元,则修改
break;
}
}
}
if(i == m_num)
{
m_val[m_num].row = row;
m_val[m_num].col = col;
m_val[m_num].data = data; //如果row行col列不存在非零元,则插入
m_num++;
ReSetRPos();
}
}
}
else
AfxMessageBox("请输入一个非零的数");
}

void CMartixA::Print(float result[][Max])
{
//将矩阵输出到二维数组result
int i,j;
for(i = 0;i<m_row;i++)
for(j = 0;j<m_col;j++)
{
result[i][j] = 0;
}
for(int k = 0;k<m_num;k++)
{
i = m_val[k].row;
j = m_val[k].col;
result[i][j] = m_val[k].data;
}
}

void CMartixA::ReSetRPos()
{
//计算rpos(每行第一个非零元素所对应的m_val位置
int num[Max],i;
for(i = 0;i<m_row;i++)
num[i] = 0;
for(i = 0;i<m_num;i++)
num[m_val[i].row]++;

for(i = 0;i<m_row;i++)
if(num[i] != 0)
break;

rpos[i] = 1;
for(int j = i+1;j<m_row;j++)
rpos[j] = rpos[j-1] + num[j-1];
}

void CMartixA::Clear()
{
//矩阵清零
m_num = 0;
for(int j = 0;j<m_row;j++)
rpos[j] = 0;
}

void CMartixA::Transpose(CMartixA ma) //将矩阵ma的转置矩阵,存放到当前矩阵
{
//求转置矩阵
m_row = ma.m_col;
m_col = ma.m_row;
m_num = ma.m_num;

if(m_num)
{
int a,b,i;
int num[Max];
int pos[Max];
for(i = 0;i<ma.m_col;i++)
num[i] = 0;
for(i = 0;i<m_num;i++)
num[ma.m_val[i].col]++;

for(i = 0;i<ma.m_col;i++)
{
if(num[i] != 0)
break;
}

pos[i] = rpos[i] = 1;
for(int j = i+1;j<ma.m_col;j++)
pos[j] = rpos[j] = rpos[j-1] + num[j-1];

for(i = 0;i<m_num;i++)
{
a = ma.m_val[i].col;
b = pos[a];
m_val[b-1].row = ma.m_val[i].col;
m_val[b-1].col = ma.m_val[i].row;
m_val[b-1].data = ma.m_val[i].data;
pos[a]++;
}
}
}

void CMartixA::Add(CMartixA ma,CMartixA& result) //当前矩阵与矩阵ma相加,存于result
{
//矩阵相加
if(ma.GetCol() != m_col||ma.GetRow() != m_row)
AfxMessageBox("两矩阵行或列不相等,不能相加!!");
else
{
result.SetCol(m_col);
result.SetRow(m_row);
int k;
for(k = 0;k<m_num;k++)
result.SetVal(m_val[k].row,m_val[k].col,m_val[k].data);
for(k = 0;k<ma.GetNum();k++)
result.AddVal(ma.m_val[k].row,ma.m_val[k].col,ma.m_val[k].data);
}
}

void CMartixA::Multiply(CMartixA ma,CMartixA& result) //当前矩阵与矩阵ma相乘,存于result
{
//矩阵相乘
if(m_col != ma.GetRow())
AfxMessageBox("两矩阵不能相乘!!");
else
{
result.SetRow(m_row);
result.SetCol(ma.GetCol());
if(m_num*ma.GetNum() != 0)
{
float temp[Max];
int i,j,k,g,tp,tp1,tcol;
for(i = 0;i<m_row;i++) //处理this的每一行
{
for(k = 0;k<ma.GetCol();k++)
temp[k] = 0; //当前行累加器清零
if(i+1 < m_row) //当前行具有的原数个数
tp = rpos[i + 1];
else
tp = m_num + 1;
for(k = rpos[i];k<tp;k++)
{
j = m_val[k-1].col;
if(j+1 < ma.GetRow()) //当前列具有的原数个数
tp1 = ma.rpos[j+1];
else
tp1 = ma.GetNum()+1;
for(g = ma.rpos[j];g<tp1;g++)
{
tcol = ma.m_val[g-1].col;
temp[tcol] = temp[tcol]+m_val[k-1].data*ma.m_val[g-1].data;
}
}
for(tcol = 0;tcol < result.GetCol();tcol++)
if(temp[tcol])
result.SetVal(i,tcol,temp[tcol]);
}
}
}
}

void CMartixA::AddVal(int row, int col, float data)
{
//矩阵加上一个数
int i,k;
if(m_num == 0)
{
m_val[m_num].row = row;
m_val[m_num].col = col;
m_val[m_num].data = data;
m_num++;
rpos[row]++;
}
else
{
for(i = 0;i<m_num;i++)
{
if(m_val[i].row > row)
{
for(k = m_num;k>i;k--)
m_val[k] = m_val[k-1];
m_val[i].data = data; //如果row行col列不存在非零元,则插入
m_val[i].col = col;
m_val[i].row = row;
m_num++;
ReSetRPos();
break;
}
if(m_val[i].row == row)
{
if(m_val[i].col > col)
{
for(k = m_num;k>i;k--)
m_val[k] = m_val[k-1];
m_val[i].data = data; //如果row行col列不存在非零元,则插入
m_val[i].col = col;
m_val[i].row = row;
m_num++;
ReSetRPos();
break;
}
if(m_val[i].col == col)
{
m_val[i].data += data; //如果row行col列已存在非零元,则再加上data
break;
}
}
}
if(i == m_num)
{
m_val[m_num].row = row;
m_val[m_num].col = col;
m_val[m_num].data = data; //如果row行col列不存在非零元,则插入
m_num++;
ReSetRPos();
}
}
if(m_val[i].data == 0) //如果两数相加后为零,则删除
{
for(k = i;k<m_num;k++)
{
m_val[k] = m_val[k+1];
}
m_num--;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: