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

原创 2006年06月09日 17:11:00

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

头文件:
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--;
 }
}

相关文章推荐

看数据结构写代码(20)稀疏矩阵(顺序存储方式)

当矩阵 的 有用信息非常少时,我们考虑将矩阵压缩存储。这就涉及到 特殊矩阵 和 稀疏矩阵。 特殊矩阵 指的是 有一定规律的 矩阵,这个矩阵 我们 只存储 部分 有用信息,其余的信息 可以通过 公式 转...

数据结构 稀疏矩阵运算器

问题描述:有输入界面(图形或文字界面都可),能区分加法、减法、乘法和转置;能处理任意输入的典型数据和进行出错数据处理(例如乘法,当第一个矩阵的列数不等于第二个矩阵的行数时);必须采用三元组作存储结构,...

数据结构Java实现——④数组——>稀疏矩阵三元组顺序存储

一、名词解释 1、稀疏矩阵 矩阵阵中非零元素较少且分布的没有规律 2、三元组存储 矩阵中的一个元素有三个属性:行号,列号,元素的值,成为三元组 3、顺序结构 对于每一...

稀疏矩阵的三元组顺序表存储表示及基本操作

/* Name: 稀疏矩阵的三元组顺序表存储表示及各种  Copyright:  Author: 巧若拙  Date: 27-10-14 21:28 Description:  -----...

稀疏矩阵的三元组顺序表存储及矩阵相乘算法小结

详细介绍了三元组存储稀疏矩阵的快速转置算法,重点介绍矩阵乘法的三种不同实现,尤其最后一种快速乘法,先把其中一个矩阵转置,再各行对应元素相乘,思想新颖,代码简洁,值得一看。...

数据结构之三元组顺序表实现稀疏矩阵运算(参考整理严蔚敏数据结构)

#include #include using namespace std; #define MAXSIZE 100 typedef int ElemType; typedef struct{ in...

数据结构:稀疏矩阵的三元组顺序表

//----------------稀疏矩阵的三元组顺序存储表示------------------- //按行序优先存储 #include #include using namespace s...

稀疏矩阵(三元组顺序表实现)

定义了一个稀疏矩阵类,有转置和相乘两个功能,主要是熟悉稀疏矩阵的三元组顺序表存储的一些操作,和一般的矩阵不同的地方,两个转置的算法,第一个是较容易想到的,书上管它叫“按需点菜”法,就是按一开始列的顺序...

稀疏矩阵——行逻辑连接的顺序三元组表

#include using namespace std; #define MAXSIZE 20 #define MAXNUM 20 #define MAXCPOT 20 #define MAXRC...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过三元组用顺序存储方式封装稀疏矩阵
举报原因:
原因补充:

(最多只允许输入30个字)