总结:
(一)在用十字链表结构表示稀疏矩阵时,矩阵中的每一个非零元素对应一个结点,每个结点五个域:行域,列域,值域,向下域和向右域,行域和列域分别存放非零元素所在的行号和列号,值域存放非零元素的值,向下域指示同一列中下一个非零元素的存储结点序号,向右域指示同一行中下一个非零元素的存储结点序号。
(二)十字链表表示稀疏矩阵的结构特点如下:
(1)稀疏矩阵每一行每一列均用带表头结点的循环链表表示;
(2)表头结点中的行域和列域的值均置为-1(即row=-1,col=-1);
(3)行、列链表的表头结点合用,且这些表头结点存放在一个顺序存储空间中。
因此,只要给出行列链表的头指针,就可以很方便地扫描到稀疏矩阵中的任意一行或一列中的非零元素。
1.十字链表表示的稀疏矩阵类:
#include <iostream>
#include <iomanip>
using namespace std;
template <class T>
struct CN
{
int i; /*非零元素行号*/
int j; /* 非零元素列号*/
T v; /* 非零元素值*/
CN<T> *down; /*向下指针*/
CN<T> *right; /*向右指针*/
};
template<class T>
class CN_Array
{
private: // 数据成员
int mm; // 稀疏矩阵行数
int nn; // 列数
int tt; // 非零元素个数
CN<T> * H; // 十字链表行列表头结点存储空间
public:
CN_Array(){H=NULL;return;} // 初始化
void in_CN_Array(); // 以三元组形式从键盘输入稀疏矩阵非零元素
void th_CN_Array(int,int,T[]); // 由一般稀疏矩阵转换
void prt_CN_Array(); // 按行输出稀疏矩阵
};
template <class T>
void CN_Array<T>::in_CN_Array()
{
int k,m,n;
T d;
CN<T> *p,*q;
cout<<"输入行数 列数 非零元素个数:"<<endl;
cin>>mm>>nn>>tt;
if(mm>=nn)m=mm;
else m=nn;
H=new CN<T>[m]; // 申请十字链表行列表头结点存储空间
for(k=0;k<m;k++)
{
H[k].i=-1;H[k].j=-1;H[k].down=&H[k];H[k].right=&H[k];
}
cout<<"输入行号 列号 非零元素"<<endl;
for(k=0;k<tt;k++)
{
cin>>m>>n>>d;
p=new CN<T>;
p->i=m-1;p->j=n-1;p->v=d;
q=&H[m-1];
while(q->right!=&H[m-1]) q=q->right; // 链接到行尾
q->right=p;p->right=&H[m-1];
q=&H[n-1];
while(q->down!=&H[n-1]) q=q->down; // 链接到列尾
q->down=p;p->down=&H[n-1];
}
return;
}
//由一般稀疏矩阵转换
template <class T>
void CN_Array<T>::th_CN_Array(int m,int n,T a[])
{
int p,q;
CN<T> *s,*k;
T d;
mm=m;nn=n;tt=0;
if(mm>nn)q=mm;
else q=nn;
H=new CN<T>[q];
for(p=0;p<q;p++)
{
H[p].i=-1;H[p].j=-1;H[p].down=&H[p];H[p].right=&H[p];
}
for(p=0;p<m;p++)
for(q=0;q<n;q++)
{
d=a[p*n+q];
if(d!=0)
{
s=new CN<T>;
s->i=p;s->j=q;s->v=d;
k=&H[p];
while(k->right!=&H[p]) k=k->right; // 链接到行尾
k->right=s;s->right=&H[p];
k=&H[q];
while(k->down!=&H[q]) k=k->down; // 链接到列尾
k->down=s;s->down=&H[q];
tt=tt+1;
}
}
return;
}
template <class T>
void CN_Array<T>::prt_CN_Array()
{
int k,kk;
CN<T> *p;
for(k=0;k<mm;k++)
{
p=&H[k];p=p->right;
for(kk=0;kk<nn;kk++) //输出一行
if(p->j==kk)
{
cout<<setw(8)<<p->v;
p=p->right;
}
else
cout<<setw(8)<<0;
cout<<endl;
}
return;
}
2.应用实例
#include "CN.Array.h"
int main()
{
double a[7][8]={
{0,0,3,0,0,0,0,1},
{0,0,0,0,0,0,0,0},
{9,0,0,0,0,0,0,0},
{0,0,0,0,7,0,0,0},
{0,0,0,0,0,0,6,0},
{0,0,0,2,0,3,0,0},
{0,0,5,0,0,0,0,0}};
CN_Array<double> x,y;
x.th_CN_Array(7,8,&a[0][0]);
cout<<"输出稀疏矩阵x:"<<endl;
x.prt_CN_Array();
y.in_CN_Array();
cout<<"输出稀疏矩阵y:"<<endl;
y.prt_CN_Array();
return 0;
}
3.实验结果