用十字連結串列表示的稀疏矩陣類

小許發表於2012-08-31

總結:

(一)在用十字連結串列結構表示稀疏矩陣時,矩陣中的每一個非零元素對應一個結點,每個結點五個域:行域,列域,值域,向下域和向右域,行域和列域分別存放非零元素所在的行號和列號,值域存放非零元素的值,向下域指示同一列中下一個非零元素的儲存結點序號,向右域指示同一行中下一個非零元素的儲存結點序號。

(二)十字連結串列表示稀疏矩陣的結構特點如下:

(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.實驗結果


 

相關文章