数据结构(java语言描述)串与数组——稀疏矩阵的三元组表存储

拟墨画扇 提交于 2020-01-20 01:22:35

知识点补充:

稀疏矩阵:是具有较多零元素且非零元素的分布无规律的矩阵。(一般矩阵是用多(二)维数组存储)。

但是,稀疏矩阵的存储比较浪费存储空间,因此为了节省存储空间可以用一个三元组表来存储稀疏矩阵。

三元组表:三元组表中的任意一个三元组元素存储了稀疏矩阵中的非零元素、所在行和所在列。

稀疏矩阵转三元表表示的原理图如下(ps手写版,比较快,将就看吧,主要是能明白^~^):

java语言表示的三元组(结点)的类形式:

package chuanshu;
class tripleNode {//三元组的定义
    private int row;//元素所在稀疏矩阵中的行号
    private int col;//元素所在稀疏矩阵中的列号
    private int value;//元素所在稀疏矩阵中的非零元素值
    public int getcol(){
        return col;
    }
    public int getrow(){
        return row;
    }
    public void setcol(int col){
        this.col=col;
    }
    public void setrow(int row){
        this.row=row;
    }
    public int getvalue(){
        return value;
    }
    public void setvalue(int value){
        this.value=value;
    }
    public tripleNode(int row,int col,int value){//带行列值参数的构造方法
        this.row=row;
        this.col=col;
        this.value=value;
    }
    public tripleNode(){//无参构造方法
        this(0,0,0);
    }
}

这是三元组表中存储一个非零元素的结点。

然后采用一个tripleNode类型的数组data来存储整个稀疏矩阵(多个元素结点构成了表的形式),此外还要设置成员变量来存储稀疏矩阵的行数、列数和非零元素的个数。cols/rows/nums

稀疏矩阵的三元组表的类定义:

package chuanshu;
/***********三元组就是用一个以为数组存储所有的元素,每个结点记录该元素在数组(矩阵)中是所在的行和列******************/
public class SparseMatrix {
private int rows;//稀疏矩阵的行数
private int cols;//稀疏矩阵总的列数
private int nums;//稀疏矩阵非0元素个数
private tripleNode data[];//三元组数据结点
public tripleNode[] getedata(){//返回某个三元组结点的数据值
    return data;
}
public void setdata(tripleNode[] data){//给三元组的数据结点赋值(三元组形式row col value)
    this.data=data;
}
public int getcosl(){//获取稀疏矩阵的的总列数
    return cols;
}
public int getrows(){//获取稀疏矩阵的的总行数
    return rows;
}
public void setcols(int cols){//设置稀疏矩阵的的总列数
    this.cols=cols;
}
public void setrows(int rows){//设置稀疏矩阵的的总行数
    this.rows=rows;
}
public int getnums(int nums){//获取整个稀疏矩阵的非零元素个数
    return nums;
}
public void setnums(int nums){//设置整个稀疏矩阵的非零元素个数
    this.nums=nums;
}
public SparseMatrix(int maxsize){//初始化函数
    data=new tripleNode[maxsize];
    for(int i=0;i<data.length;i++){
        data[i]=new tripleNode();
    }
    rows=0;
    cols=0;
    nums=0;
}
public SparseMatrix(int mat[][]){//用数组初始化的构造函数
    int i,j,k=0,count=0;
    rows=mat.length;
    cols=mat.length;
    for(i=0;i<mat.length;i++){//先计算数组mat[][]的非零元素个数
        for(j=0;j<mat.length;j++){
            if(mat[i][j]!=0){
                count++;
            }
        }
    }
    nums=count;
    data=new tripleNode[nums];//初始化三元组(顺序表存储模式)
    for(i=0;i<mat.length;i++){
        for(j=0;j<mat.length;j++){
            if(mat[i][j]!=0){
                data[k]=new tripleNode(i,j,mat[i][j]);//把mat[][]中所有不等于零的元素赋值给三元组
                k++;
            }
        }
    }
}
public void printMatrix(){//打印整个三元组的所有结点
    int i;
    System.out.println("稀疏矩阵的三元组存储结构:");
    System.out.println("行数:"+rows+"列数:"+cols+"非零元素的个数:"+nums);
    System.out.println("行下标 列下标 元素值");
    for(i=0;i<nums;i++){
        System.out.println(data[i].getrow()+"\t"+data[i].getcol()+"\t"+data[i].getvalue());
    }
}

/******转置思想:初始化一个新的三元组表;然后,对稀疏举证的n列进行扫描,当扫描第i列的时候,遍历整个三元组表的t个元素。若元素所在列=i,则将这个元素的值赋给新的三元组表的结点值,然后让这个元素的列作为新三元组表元素的行,这个元素的行作为新三元组表元素的列,另新三元组表元素下标加1;*****/

/***************算法时间复杂度O(nt),空间复杂度O(t)****************************/
public SparseMatrix transpose(){//返回的是一个三元组对象,转置
    SparseMatrix tm=new SparseMatrix(nums);
    tm.cols=rows;
    tm.rows=cols;
    tm.nums=nums;
    int q=0;//三元组结点data[]的下标
    for(int col=0;col<cols;col++){
        for(int p=0;p<nums;p++){
            if(data[p].getcol()==col){
                tm.data[q].setrow(data[p].getcol());
                tm.data[q].setcol(data[p].getrow());
                tm.data[q].setvalue(data[p].getvalue());
                q++;//
            }
        }
    }
    return tm;
}

/***********fasttranspose方法:初始化一个三元组表;然后,分别计算原稀疏矩阵每列之前的非零元素个数,即为转置后的每行元素之前的非零元素的个数赋值给num[cols],***************/

/**************************/
public SparseMatrix  fasttranspose(){//返回的是一个三元组表对象,快速转置
    SparseMatrix tm=new SparseMatrix(nums);//生成一个新的三元组表对象
    tm.cols=rows;
    tm.rows=cols;
    tm.nums=nums;//设置新表的列行和非零元素个数
    int i,j=0,k=0;
    int[] num,cpot;
    if(nums>0){
        num=new int[cols];//初始化一个列数大小的数组
        cpot=new int[cols];//初始化一个列数大小的数组
        for(i=0;i<cols;i++){
            num[i]=0;
        }
        for(i=0;i<nums;i++){
            j=data[i].getcol();//获取每个非零元素在原稀疏矩阵N中所在的列数
            num[j]++;//计算每列有多少个非零元素,num[j]最终存储原稀疏矩阵N中每列非零元素的个数
        }
        cpot[0]=0;
        for(i=1;i<cols;i++){//对1到总列数进行遍历
            cpot[i]=cpot[i-1]+num[i-1];//cpot[i]表示原稀疏矩阵N中第i列的第一个元素在转置后的稀疏矩阵M的三元组表TM中的位置(下标)
        }
        for(i=0;i<nums;i++){//对TN所有的非零元素进行遍历
            j=data[i].getcol();//返回原TN第i个非零元素所在的列数
            k=cpot[j];//返回N中第j列的第一个非零元素在TM中的下标
            tm.data[k].setrow(data[i].getcol());
            tm.data[k].setcol(data[i].getrow());
            tm.data[k].setvalue(data[i].getvalue());
            cpot[j]++;/***/N中的同一列中的元素大于一则执行+1,即该元素在TM中的下标加1(N中的同一列即为M中的同一行,所以TN中同一列的元素不相邻,但在TM中相邻)****/

图示:


        }
    }
    return tm;
}
}
调用的主函数:

package chuanshu;
public class juzhen {
    public static void main(String[] args){
        int m[][]={{0,0,8,0,0,0},{0,0,0,0,0,0},{5,0,0,0,16,0},{0,0,18,0,0,0},{0,0,0,9,0,0}};
        SparseMatrix sm=new SparseMatrix(m);
        SparseMatrix tm=sm.transpose();
        SparseMatrix tsm=sm.fasttranspose();
        sm.printMatrix();
        tm.printMatrix();
        tsm.printMatrix();
    }
}

结果:

稀疏矩阵的三元组存储结构:
行数:5列数:6非零元素的个数:5
行下标 列下标 元素值
0    2    8
2    0    5
2    4    16
3    2    18
4    3    9
稀疏矩阵的三元组存储结构:
行数:6列数:5非零元素的个数:5
行下标 列下标 元素值
0    2    5
2    0    8
2    3    18
3    4    9
4    2    16
稀疏矩阵的三元组存储结构:
行数:6列数:5非零元素的个数:5
行下标 列下标 元素值
0    2    5
2    0    8
2    3    18
3    4    9
4    2    16

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!