您的位置:首页 > 其它

稀疏矩阵--三元组表来压缩存储及转置

2011-07-27 19:26 411 查看
  今天看到第五章《数组和广义表》了,其中的矩阵的存储我其实已经习惯用一个数组了,今天看到这儿,就写了不同的方法来存储(号称能节约大量空间),书(《数据结构c语言版》--严蔚敏、吴伟民 清华大学出版社)上的讲法是:通常,用高级语言编制程序时都是用二维数组来存储矩阵元....然而,在数值分析中经常出现一些阶数很高的矩阵,同时在矩阵中哟许多相同的元素或者是0元素,有时候为了节省存储空间可以对这类矩阵进行压缩存储; 所谓的压缩存储其实就是指的为多个相同值的元只分配一个存储空间,对零元则不分配空间。

  首先,稀疏矩阵在书上的定义是:假若值相同的元素或者零元素在矩阵中有一定的分布规律,则称之为特殊矩阵,反之,成为稀疏矩阵;其中特殊矩阵都有自己的方法来压缩,比如,对角矩阵就以对角线的顺序将其压缩到一维数组上,我觉得特殊矩阵各有各的特殊情况,还不如直接用个数组来存储来的方便,在这里就不赘述了。

  而稀疏矩阵却是没有确切的定义的,反之元素少到一定的程度就是稀疏了,具体的值是m*n的矩阵中,t个非0元素,若t/(m*n)<=0.05就是了。

上面废话说了那么多,简单的看这张图就知道我的目的了

main

/*
2011-7-27 zhangming
5.3 矩阵压缩 之稀疏矩阵的压缩
方法一:“三元组顺序表”来存储
*/
#include "TSMatrix.h"
void transMatrix(TSMatrix a,TSMatrix &b);//求三元组顺序表方式,转置矩阵简单的方法,将稀疏矩阵a转置为b
void quickTransMatrix(TSMatrix a,TSMatrix &b);//快速转置法
int main(){
Triple a_matrix[8];
a_matrix[0] = Triple(0,1,12);//先前的错误写法 t[0] = new Triple(1,2,12);
a_matrix[1] = Triple(0,2,9);
a_matrix[2] = Triple(2,0,-3);
a_matrix[3] = Triple(2,5,14);
a_matrix[4] = Triple(3,2,24);
a_matrix[5] = Triple(4,1,18);
a_matrix[6] = Triple(5,0,15);
a_matrix[7] = Triple(5,3,-7);

Triple b_matrix[8];//简单转置法
Triple c_matrix[8];//快速转置法

TSMatrix a = TSMatrix(7,6,8);//建立了一个7*6的数组,里面的非零元有8个
TSMatrix b = TSMatrix();
TSMatrix c = TSMatrix();

a.setMatrix(a_matrix);
b.setMatrix(b_matrix);
c.setMatrix(c_matrix);
int flag = 0;
cout<<"a矩阵如下:\n";
for(int i = 0,flag = 0; i< a.getRows();i++){
for(int j = 0; j < a.getCols(); j++){
if(a.getMatrix()[flag].getI()==i&&a.getMatrix()[flag].getJ()==j){
cout<<a.getMatrix()[flag].getData()<<"\t";
flag++;
}else{
cout<<"0\t";
}
}
cout<<endl;
}
cout<<endl;
cout<<"存储的实际上是这些:";
for(int i =0; i < 8;i++){
cout<<" ("<<a.getMatrix()[i].getI()<<","<<a.getMatrix()[i].getJ()<<","<<a.getMatrix()[i].getData()<<") ";
}
cout<<endl;
//开始转置
transMatrix(a,b);
quickTransMatrix(a,c);
cout<<endl<<"简单转置法转置后:\n";
for(int i = 0,flag = 0; i< b.getRows();i++){
for(int j = 0; j < b.getCols(); j++){
if(b.getMatrix()[flag].getI()==i&&b.getMatrix()[flag].getJ()==j){
cout<<b.getMatrix()[flag].getData()<<"\t";
flag++;
}else{
cout<<"0\t";
}
}
cout<<endl;
}
cout<<endl;
cout<<endl<<"快速转置法转置后:\n";
for(int i = 0,flag = 0; i< b.getRows();i++){
for(int j = 0; j < b.getCols(); j++){
if(b.getMatrix()[flag].getI()==i&&b.getMatrix()[flag].getJ()==j){
cout<<b.getMatrix()[flag].getData()<<"\t";
flag++;
}else{
cout<<"0\t";
}
}
cout<<endl;
}
system("pause");
}
void transMatrix(TSMatrix a,TSMatrix &b){//求三元组顺序表方式,转置矩阵简单的方法,将稀疏矩阵a转置为b
b.setRows(a.getCols());//将a 的列数设置为b的行数
b.setCols(a.getRows());//将a 的行数设置为b的列数
b.setNum(a.getNum());//总数都一样
if(b.getNum()>0){//如果总数大于0
int flag = 0;
for(int i = 0; i < a.getRows();i++){
for(int j = 0; j < a.getNum();j++ ){
/*
没有设置为公共属性,下面的写法看起来有些蛋疼。。,如果都设置为公共属性的话就是这个样子了a.matrix[i].j =
下面的操作就是给b矩阵赋值
*/
if(a.getMatrix()[j].getJ() ==i){
b.getMatrix()[flag].setI(a.getMatrix()[j].getJ());
b.getMatrix()[flag].setJ(a.getMatrix()[j].getI());
b.getMatrix()[flag].setData(a.getMatrix()[j].getData());
flag++;
}
}
}
}

}
void quickTransMatrix(TSMatrix a,TSMatrix &b){
b.setRows(a.getCols());//将a 的列数设置为b的行数
b.setCols(a.getRows());//将a 的行数设置为b的列数
b.setNum(a.getNum());//总数都一样

int* closNum = new int[a.getCols()];//存储每列的非0元的个数
int* closPos = new int[a.getCols()];//存储每列的第一个非零元出现的位置
if(a.getNum()>0){
for(int i = 0; i < a.getCols();i++){//都初始化为0
closNum[i]=0;
}
for(int i = 0; i < a.getNum();i++){//扫描a里的所有元素,求出每一列中非0元的个数
closNum[a.getMatrix()[i].getJ()]++;
}
closPos[0] = 0;
for(int i = 1 ; i < a.getCols();i++){//确定矩阵a中的的第i列中第一个非零元素在b中的位置
closPos[i] = closPos[i-1] + closNum[i-1];
}
for(int i = 0 ; i < a.getNum();i++){
int k = closPos[a.getMatrix()[i].getJ()]; //k即矩阵a第j列中第一个非零元素在b中的位置
b.getMatrix()[k].setI(a.getMatrix()[i].getJ());
b.getMatrix()[k].setJ(a.getMatrix()[i].getI());
b.getMatrix()[k].setData(a.getMatrix()[i].getData());
closPos[a.getMatrix()[i].getJ()]++;//矩阵a第col列中第一个非零元素在b中的位置向前移动一位
}
}
delete []closNum;
delete []closPos;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: