用三列二維陣列表示的稀疏矩陣類
1.稀疏矩陣:矩陣中絕大多數的元素值為零,只有少數的非零元素值;
2.對稀疏矩陣採用壓縮儲存的目的是為了節省儲存空間,並且,稀疏矩陣壓縮儲存後,還要能夠比較方便地訪問其中的沒個元素(包括零元素和非零元素);
3.對稀疏矩陣進行壓縮儲存有兩種方法:稀疏矩陣的三列二維陣列表示和十字連結串列方法。
稀疏矩陣的三列二維陣列表示:
(1)每個非零元素用三元組表示:(i,j,v)分別對應(行,列,非零元素);
(2) 為了表示唯一性,除了每個非零元素用一個三元組表示外,在所有的非零元素三元組之前新增一組資訊(I,J,V)對應(總行數,總列數,非零元素個數),也就是說,我們要確定確切的稀疏矩陣,必須先知道該稀疏矩陣的總行數,總列數,非零個數;
(3)為了便於在三列二維陣列B中訪問稀疏矩陣A中的各元素,通常還附設兩個長度與稀疏矩陣A的行數相同的向量POS與NUM。其中POS[K]表示稀疏矩陣A中的第k行的第一個非零元素(如果有的話)在三列二維組B中的行號;NUM[k]表示稀疏矩陣A中第k行中非零元素的個數;
pos[0]=0; pos[k]=pos[k-1]+num[k-1]
4.三列二維陣列表示的稀疏矩陣類如下:
檔名:X_Array.h
#include <iostream>
#include <iomanip>
using namespace std;
template <class T>
struct B
{
int i; //非零元素所在行號
int j; //非零元素所在列號
T v; //非零元素值
};
//三列二維陣列表示的稀疏矩陣類
template <class T>
class X_Array
{
private:
int mm; //稀疏矩陣行數
int nn; //稀疏矩陣列數
int tt; //非零個數
B<T> *bb; //三列二維陣列空間
int *pos; //某行第一個非零元素在b中的下標
int *num; //某行非零元素的個數
public:
void in_X_Array(); // 以三元組形式鍵盤輸入稀
void cp_X_Array(int,int,int,B<T>[]); // 複製三元陣列
void th_X_Array(int,int,T[]); // 由一般稀疏矩陣轉換
void prt_X_Array(); // 按行輸出稀疏矩陣
X_Array tran_X_Array(); // 稀疏矩陣轉置
X_Array operator +(X_Array &); // 稀疏矩陣相加
X_Array operator *(X_Array &); // 稀疏矩陣相乘
};
// 以三元組形式鍵盤輸入稀疏矩陣非零元素
template <class T>
void X_Array<T>::in_X_Array()
{
int k,m,n;
cout<<"輸入行數 列數 非零元素個數:"<<endl;
cin>>mm>>nn>>tt;
bb=new B<T>[tt];
cout<<"輸入行號 列號 非零元素值:"<<endl;
for(k=0;k<tt;k++)
{
cin>>m>>n>>bb[k].v;
bb[k].i=m-1;
bb[k].j=n-1;
}
pos=new int[mm];
num=new int[mm];
for(k=0;k<mm;k++) //num向量初始化
num[k]=0; //初始化mm行的每行num都設為零
for(k=0;k<tt;k++)
num[bb[k].i]=num[bb[k].i]+1; //提取每個非零元素的行號,出現行號的陣列num值加1,當n個非零元素在同一行時,則加n次。
pos[0]=0;
for(k=1;k<mm;k++) //構造pos向量
pos[k]=pos[k-1]+num[k-1]; //pos[k]表示在稀疏矩陣第k行中第一個非零元素在陣列B中的行號
return;
}
//複製三元陣列
template <class T>
void X_Array<T>::cp_X_Array(int m,int n,int t,B<T> b[])
{
int k;
mm=m;
nn=n;
tt=t;
bb=new B<T>[tt];
for(k=0;k<tt;k++)
{
bb[k].i=b[k].i-1;
bb[k].j=b[k].j-1;
bb[k].v=b[k].v;
}
pos=new int[mm];
num=new int[mm];
for(k=0;k<mm;k++) //num向量初始化
num[k]=0; //初始化mm行的每行num都設為零
for(k=0;k<tt;k++)
num[bb[k].i]=num[bb[k].i]+1; //提取每個非零元素的行號,出現行號的陣列num值加1,當n個非零元素在同一行時,則加n次。
pos[0]=0;
for(k=1;k<mm;k++) //構造pos向量
pos[k]=pos[k-1]+num[k-1]; //pos[k]表示在稀疏矩陣第k行中第一個非零元素在陣列B中的行號
return;
}
// 由一般稀疏矩陣轉換
template <class T>
void X_Array<T>::th_X_Array(int m,int n,T a[])
{
int k,t=0,p,q;
T d;
for(k=0;k<m*n;k++) //統計非零個數
if(a[k]!=0) t++;
mm=m;nn=n;tt=t;
bb=new B<T>[tt];
k=0;
for(p=0;p<m;p++)
for(q=0;q<n;q++)
{
d=a[p*n+q];
if(d!=0) //非零元素
{
bb[k].i=p;
bb[k].j=q;
bb[k].v=d;
k=k+1;
}
}
pos=new int[mm];
num=new int[mm];
for(k=0;k<mm;k++) //num向量初始化
num[k]=0; //初始化mm行的每行num都設為零
for(k=0;k<tt;k++)
num[bb[k].i]=num[bb[k].i]+1; //提取每個非零元素的行號,出現行號的陣列num值加1,當n個非零元素在同一行時,則加n次。
pos[0]=0;
for(k=1;k<mm;k++) //構造pos向量
pos[k]=pos[k-1]+num[k-1]; //pos[k]表示在稀疏矩陣第k行中第一個非零元素在陣列B中的行號
return;
}
// 按行輸出稀疏矩陣
template <class T>
void X_Array<T>::prt_X_Array()
{
int k,kk,p;
for(k=0;k<mm;k++) //按行輸出
{
p=pos[k];
for(kk=0;kk<nn;kk++) //輸出一行
if((bb[p].i==k)&&(bb[p].j==kk)) //輸出非零元素
{
cout<<setw(8)<<bb[p].v;p=p+1;
}
else
cout<<setw(8)<<0;
cout<<endl;
}
return;
}
// 稀疏矩陣轉置
template <class T>
X_Array<T> X_Array<T>::tran_X_Array()
{
X_Array<T> at; //定義轉置矩陣物件
int k,p,q;
at.mm=nn;
at.nn=mm;
at.tt=tt;
at.bb=new B<T>[tt];
k=0;
for(p=0;p<nn;p++) //按列掃描所有非零元素
for(q=0;q<tt;q++)
{
if(bb[q].j==p) // 將非零元素一次存放到轉置矩陣的三列二維陣列中
{
at.bb[k].i=bb[q].j;
at.bb[k].j=bb[q].i;
at.bb[k].v=bb[q].v;
k++;
}
}
at.pos=new int[at.mm];
at.num=new int[at.mm];
for(k=0;k<at.mm;k++)
at.num[k]=0;
for(k=0;k<at.tt;k++)
at.num[at.bb[k].i]=at.num[at.bb[k].i]+1;
at.pos[0]=0;
for(k=1;k<at.mm;k++)
at.pos[k]=at.pos[k-1]+at.num[k-1];
return (at); //返回轉置矩陣
}
// 稀疏矩陣相加
template <class T>
X_Array<T> X_Array<T>::operator+ (X_Array<T> &b)
{
X_Array<T> c;
B<T> *a;
T d;
int m,n,k,p;
if((mm!=b.mm)||(nn!=b.nn))
cout<<"不能相加!"<<endl;
else
{
a=new B<T>[tt+b.tt]; //臨時申請一個三列二維陣列空間
p=0;
for(k=0;k<mm;k++) //逐行處理
{
m=pos[k];n=b.pos[k];
while((bb[m].i==k)&&(b.bb[n].i==k)) //行號相同
{
if(bb[m].j==b.bb[n].j) //列號相同則相加
{
d=bb[m].v+b.bb[n].v;
if(d!=0) //相加後非零
{
a[p].i=k;a[p].j=bb[m].j;
a[p].v=d;p=p+1;
}
m=m+1;n=n+1;
}
else if(bb[m].j<b.bb[n].j) //列號不同則複製列號小的一項
{
a[p].i=k;a[p].j=bb[m].j;
a[p].v=bb[m].v;p=p+1;
m=m+1;
}
else //列號不同複製另一項
{
a[p].i=k;a[p].j=b.bb[m].j;
a[p].v=b.bb[m].v;p=p+1;
n=n+1;
}
}
while(bb[m].i==k) //複製矩陣中本行剩餘的非零元素
{
a[p].i=k;a[p].j=bb[m].j;
a[p].v=bb[m].v;p=p+1;
m=m+1;
}
while(b.bb[n].i==k) //複製另一矩陣中本行剩餘的非零元素
{
a[p].i=k;a[p].j=b.bb[m].j;
a[p].v=b.bb[m].v;p=p+1;
n=n+1;
}
}
c.mm=mm;c.nn=nn;c.tt=p;
c.bb=new B<T>[p]; //申請一個三列二維陣列空間
for(k=0;k<p;k++) //複製臨時三列二維陣列空間中的元素
{
c.bb[k].i=a[k].i;
c.bb[k].j=a[k].j;
c.bb[k].v=a[k].v;
}
delete a; //釋放臨時三列二維陣列空間
c.pos=new int[c.mm];
c.num=new int[c.mm];
for(k=0;k<c.mm;k++)
c.num[k]=0;
for(k=0;k<c.tt;k++)
c.num[c.bb[k].i]=c.num[c.bb[k].i]+1;
c.pos[0]=0;
for(k=1;k<c.mm;k++)
c.pos[k]=c.pos[k-1]+c.num[k-1];
}
return c;
}
template <class T>
X_Array<T> X_Array<T>::operator* (X_Array<T> &b)
{
X_Array<T> cc;
int k,m,n,p,t;
T *c; //定義乘積矩陣
if(nn!=b.mm)
cout<<"兩矩陣無法相乘!"<<endl;
else
{
c=new T[mm*b.nn]; //申請乘積矩陣的臨時空間
k=0;
for(m=0;m<mm;m++)
{
for(n=0;n<b.nn;n++)
{
c[k]=0;k=k+1; //乘積矩陣元素初始化為零
}
}
for(m=0;m<tt;m++) //對於左矩陣中的每一個非零元素
{
k=bb[m].j; //左矩陣中非零元素的列值K
n=b.pos[k]; //右矩陣中行號與K相同的第一個非零元素的位置
t=b.pos[k]+b.num[k];//右矩陣中行號與k相同的最後一個非零元素的位置
while(n!=t)
{
p=bb[m].i*b.nn+b.bb[n].j;//在乘積矩陣中的位置
c[p]=c[p]+bb[m].v*b.bb[n].v;//累加非零元素的乘積
n=n+1;
}
}
cc.th_X_Array(mm,b.nn,c); //由一般的稀疏矩陣轉換成用三列二維陣列表示
delete c; //釋放乘積矩陣的臨時空間
}
return cc;
}
2.例項應用:
#include "test2.h"
#include<stdlib.h>
int main()
{
B<double> a[8]={{1,3,3.0},{1,8,1.0},{3,1,9.0},{4,5,7.0},{5,7,6.0},{6,4,2.0},{6,6,3.0},{7,3,5.0}};
X_Array<double> x,y,z,xt,c;
x.cp_X_Array(7,8,8,a);
cout<<"輸出稀疏矩陣X:"<<endl;
x.prt_X_Array();
xt=x.tran_X_Array();
cout<<"輸出稀疏矩陣x的轉置xt:"<<endl;
xt.prt_X_Array();
y.in_X_Array();
cout<<"輸出稀疏矩陣y:"<<endl;
y.prt_X_Array();
z=x+y;
cout<<"輸出稀疏矩陣z=x+y"<<endl;
z.prt_X_Array();
c=x*xt;
cout<<"輸出稀疏矩陣c=x*y"<<endl;
c.prt_X_Array();
system("pause");
return 0;
}
3.實驗結果:
相關文章
- 二維陣列和稀疏陣列互轉陣列
- 資料結構:陣列,稀疏矩陣,矩陣的壓縮。應用:矩陣的轉置,矩陣相乘資料結構陣列矩陣
- 用十字連結串列表示的稀疏矩陣類矩陣
- 用三元組連結串列表示的稀疏矩陣類矩陣
- 稀疏矩陣矩陣
- Java陣列宣告建立和使用以及多維陣列、Arrays類、稀疏陣列Java陣列
- 資料結構之陣列和矩陣--矩陣&不規則二維陣列資料結構陣列矩陣
- 矩陣中最大的二維矩陣矩陣
- Java實現普通二維陣列和稀疏陣列的相互轉換Java陣列
- PHP一維陣列轉二維陣列正規表示式PHP陣列
- JavaSE 陣列:一維陣列&二維陣列Java陣列
- 稀疏矩陣轉置矩陣
- 稀疏陣列陣列
- Wannafly模擬賽 矩陣 二維矩陣hash矩陣
- 【scipy 基礎】--稀疏矩陣矩陣
- 稀疏陣列、佇列陣列佇列
- js 一維陣列轉二維陣列JS陣列
- js 二維陣列轉一維陣列JS陣列
- PHP二維陣列轉一維陣列PHP陣列
- 脈動陣列在二維矩陣乘法及卷積運算中的應用陣列矩陣卷積
- 二維陣列陣列
- C++ 練氣期之二維陣列與矩陣運算C++陣列矩陣
- PHP中二維陣列與多維陣列PHP陣列
- JavaScript --二維陣列查詢一維陣列JavaScript陣列
- C/C++ 二維陣列的理解(多維陣列)C++陣列
- CUDA版本稀疏矩陣向量乘矩陣
- OpenMP 版本稀疏矩陣向量乘矩陣
- 240. 搜尋二維矩陣 II 和74. 搜尋二維矩陣矩陣
- 第四章:多維陣列和矩陣 --------------- 4.1 基礎題:順時針列印二維陣列陣列矩陣
- 20_稀疏陣列陣列
- 矩陣和陣列矩陣陣列
- JavaScript二維陣列轉換成一維陣列JavaScript陣列
- vector 二維陣列陣列
- Java二維陣列Java陣列
- JavaScript二維陣列JavaScript陣列
- JavaScript 二維陣列JavaScript陣列
- 二維陣列排序陣列排序
- 指標陣列和陣列指標與二維陣列指標陣列