数据结构之——稀疏矩阵

来源:互联网 发布:医学数据可视化ppt 编辑:程序博客网 时间:2024/06/04 18:54

稀疏矩阵

在矩阵中,若数值为0的元素数目远远多于非0元素的数目时,则称该矩阵为稀疏矩阵。我们使用三元组来存放非零元素,row为横坐标,column为纵坐标,value为值。
这里写图片描述

本篇介绍的是稀疏矩阵的数据结构、普通转置快速转置的方法。

三元组节点

//节点class TripleNode {     public int row;// 行号     public int column;// 列号     public int value;// 值     public TripleNode() {           this(0, 0, 0);     }     public TripleNode(int row, int column, int value) {           this.row = row;           this.column = column;           this.value = value;     }}

稀疏矩阵转化为三元组

基本思想是:首先计算矩阵中非零元素的个数,然后创建三元组数组,循环遍历整个矩阵,分别把非零元素的横坐标,纵坐标,值放入三元组的节点。

// 将稀疏矩阵变为三元组     public SparesMatrix(int[][] mat) {           rows = mat.length;           cols = mat[0].length;           // 计算非零元素的个数           for (int i = 0; i < rows; i++) {                for (int j = 0; j < mat[i].length; j++) {                     if (mat[i][j] != 0) {                           nums++;                     }                }           }           int k = 0;           data = new TripleNode[nums];           for (int i = 0; i < mat.length; i++) {                for (int j = 0; j < mat[i].length; j++) {                     if (mat[i][j] != 0) {                           data[k] = new TripleNode(i, j, mat[i][j]);                           k++;// 由于非零元素个数已知,所以不会越界                     }                }           }     }

普通转置

这里写图片描述

如图,我们可以看到,转置就是横坐标与纵坐标进行互换。

普通转置的基本思想:创建一个三元组,对原三元组进行遍历,从列为0开始在原三元组中找到最小列的非零元素,存入转置三元组。

这个算法的复杂度为 O(n*t)
n为矩阵的列数,t为三元组中非零元素个数。

// 普通转置     public SparesMatrix transpose() {           SparesMatrix tmMatrix = new SparesMatrix(nums);           tmMatrix.cols = rows;           tmMatrix.rows = cols;           tmMatrix.nums = nums;           int q = 0;           // 转置并按先行后列排序           for (int col = 0; col < cols; col++) {                for (int p = 0; p < nums; p++) {                     if (data[p].column == col) {// 遍历整个三元组从最小的列开始寻找,原来的三元组已经是排序好的,只需要按照列最小寻找就好                           tmMatrix.data[q].column = data[p].row;                           tmMatrix.data[q].row = data[p].column;                           tmMatrix.data[q].value = data[p].value;                           q++;                     }                }           }           return tmMatrix;     }

快速转置

基本思想:由于转置时,列变成了行,所以我们从每列出发,寻找每列中第一个非零元素,并在转置三元组中计算它的位置。最后遍历原三元组,来完成转置三元组。

算法复杂度为 O(n+t),n为矩阵的列,t为非零元素个数。

这里写图片描述

例如:我们先找到第0列的第一个非零元素,它在转置三元组中的位置为0,计算这个列中共有2个非零元素,那么寻找到第二列的第一个非零元素时,它在转置三元组的位置就是0+2=2

这里使用到了两个数组:
num[x] , x表示列,值表示非零元素个数
cpot[x] , x表示列,值表示该列非零元素在转置三元组的位置

必须要读num进行初始化,其每个值表示每列的非零个数,0则表示该列全为0,无非零元素。

  // 对num[]初始化           for (int i = 0; i < cols; i++) {                num[i] = 0;           }

默认cpot[0]=0,如果第0列不存在非零元素,会被覆盖,即
cpot[1] = cpot[0] + num[0] = 0
cpot[1] = 0

 cpot[0] = 0;           // 计算位置           for (int i = 1; i < cols; i++) {                cpot[i] = cpot[i - 1] + num[i - 1];// 每列第一个非零元素在转置三元组的位置           }

// 快速转置     public SparesMatrix fasttanspose() {           SparesMatrix tMatrix = new SparesMatrix(nums);           tMatrix.rows = cols;           tMatrix.cols = rows;           tMatrix.nums = nums;           int[] num = null;// 每列非零元素的个数,下标表示列,值表示元素个数           int[] cpot = null;// 每列首个非零元素在转置三元组的位置,下标表示列,值表示位置           // 初始化           if (nums > 0) {                num = new int[cols];                cpot = new int[cols];           }           // 对num[]初始化           for (int i = 0; i < cols; i++) {                num[i] = 0;           }           int j = 0;           // 计算每列非零元素的个数           for (int i = 0; i < nums; i++) {                j = data[i].column;                num[j]++; // 同一列有非零元素,值加1           }           cpot[0] = 0;           // 计算位置           for (int i = 1; i < cols; i++) {                cpot[i] = cpot[i - 1] + num[i - 1];// 每列第一个非零元素在转置三元组的位置           }           j = 0;           int k = 0;           // 对原三元组进行相应的转换           for (int i = 0; i < nums; i++) {// 对原三元组进行遍历                j = data[i].column;                k = cpot[j];// 转置三元组中的位置                tMatrix.data[k].column = data[i].row;                tMatrix.data[k].row = data[i].column;                tMatrix.data[k].value = data[i].value;                cpot[j]++;// 同列下一个非零元素的位置           }           return tMatrix;     }

完整代码

//节点class TripleNode {     public int row;// 行号     public int column;// 列号     public int value;// 值     public TripleNode() {           this(0, 0, 0);     }     public TripleNode(int row, int column, int value) {           this.row = row;           this.column = column;           this.value = value;     }}// 稀疏矩阵public class SparesMatrix {     public TripleNode[] data;// 三元组     public int cols;// 整个矩阵的列数     public int rows;// 整个矩阵的行数     public int nums;// 非零元素个数     // 分配三元组的存储空间     public SparesMatrix(int maxSize) {           data = new TripleNode[maxSize];           //要对每个data[] 初始化           for (int i = 0; i < maxSize; i++) {                data[i] = new TripleNode();           }           rows = 0;           cols = 0;           nums = 0;     }     public SparesMatrix() {     }     // 将稀疏矩阵变为三元组     public SparesMatrix(int[][] mat) {           rows = mat.length;           cols = mat[0].length;           // 计算非零元素的个数           for (int i = 0; i < rows; i++) {                for (int j = 0; j < mat[i].length; j++) {                     if (mat[i][j] != 0) {                           nums++;                     }                }           }           int k = 0;           data = new TripleNode[nums];           for (int i = 0; i < mat.length; i++) {                for (int j = 0; j < mat[i].length; j++) {                     if (mat[i][j] != 0) {                           data[k] = new TripleNode(i, j, mat[i][j]);                           k++;// 由于非零元素个数已知,所以不会越界                     }                }           }     }     // 打印     public void display() {           System.out.println("Matrix's rows is " + rows + "\t" + "colmns is " + cols);           System.out.println("rows" + "\t" + "colmns" + "\t" + "values");           for (int i = 0; i < data.length; i++) {                System.out.println(data[i].row + "\t" + data[i].column + "\t" + data[i].value);           }     }     // 普通转置     public SparesMatrix transpose() {           SparesMatrix tmMatrix = new SparesMatrix(nums);           tmMatrix.cols = rows;           tmMatrix.rows = cols;           tmMatrix.nums = nums;           int q = 0;           // 转置并按先行后列排序           for (int col = 0; col < cols; col++) {                for (int p = 0; p < nums; p++) {                     if (data[p].column == col) {// 遍历整个三元组从最小的列开始寻找,原来的三元组已经是排序好的,只需要按照列最小寻找就好                           tmMatrix.data[q].column = data[p].row;                           tmMatrix.data[q].row = data[p].column;                           tmMatrix.data[q].value = data[p].value;                           q++;                     }                }           }           return tmMatrix;     }     // 快速转置     public SparesMatrix fasttanspose() {           SparesMatrix tMatrix = new SparesMatrix(nums);           tMatrix.rows = cols;           tMatrix.cols = rows;           tMatrix.nums = nums;           int[] num = null;// 每列非零元素的个数,下标表示列,值表示元素个数           int[] cpot = null;// 每列首个非零元素在转置三元组的位置,下标表示列,值表示位置           // 初始化           if (nums > 0) {                num = new int[cols];                cpot = new int[cols];           }           // 对num[]初始化           for (int i = 0; i < cols; i++) {                num[i] = 0;           }           int j = 0;           // 计算每列非零元素的个数           for (int i = 0; i < nums; i++) {                j = data[i].column;                num[j]++; // 同一列有非零元素,值加1           }           cpot[0] = 0;           // 计算位置           for (int i = 1; i < cols; i++) {                cpot[i] = cpot[i - 1] + num[i - 1];// 每列第一个非零元素在转置三元组的位置           }           j = 0;           int k = 0;           // 对原三元组进行相应的转换           for (int i = 0; i < nums; i++) {// 对原三元组进行遍历                j = data[i].column;                k = cpot[j];// 转置三元组中的位置                tMatrix.data[k].column = data[i].row;                tMatrix.data[k].row = data[i].column;                tMatrix.data[k].value = data[i].value;                cpot[j]++;// 同列下一个非零元素的位置           }           return tMatrix;     }     public static void main(String[] args) {           int mat[][] = { { 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 } };           SparesMatrix sMatrix = new SparesMatrix(mat);           sMatrix.display();           System.out.println();           sMatrix.transpose().display();           System.out.println();           sMatrix.fasttanspose().display();     }}

结果显示:

Matrix's rows is 5   colmns is 6rows colmns     values0    2    82    0    52    4    163    2    184    3    9Matrix's rows is 6   colmns is 5rows colmns     values0    2    52    0    82    3    183    4    94    2    16Matrix's rows is 6   colmns is 5rows colmns     values0    2    52    0    82    3    183    4    94    2    16