稀疏矩阵

稀疏矩阵(二维数组)

1、矩阵中分布有大量的元素 0,即非 0 元素非常少

2、稀疏矩阵的压缩存储,数据结构提供有 3 种具体实现方式:

(1)三元组顺序表

(2)行逻辑链接的顺序表

(3)十字链表

 

三元组顺序表(压缩存储稀疏矩阵)

1、记录数组一共有几行几列,有多少个不同的值

2、把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小程序的规模

3、至少需要存储以下信息

(1)矩阵中各非 0 元素的值,以及所在矩阵中的行标和列标

(2)矩阵的总行数和总列数

4、例

(1)稀疏矩阵

(2)存储的是三元组(即由 3 部分数据组成的集合),组中数据分别表示(行标,列标,元素值),这里矩阵的行标和列标都从 1 开始,省略一组(行数,列数,非 0 数据个数)

 

转换思路

1.稀疏矩阵转换三元组顺序表

(1)遍历原始稀疏矩阵,得到有效数据的个数sum

(2)创建三元组顺序表 sparseArr int[sum+1][3]

(3)将稀疏矩阵的有效数据存入到三元组顺序表中

2.三元组顺序表转换稀疏矩阵

(1)先读取三元组顺序表的第一行(下标为0的一维数组)

(2)根据第一行的数据,创建原始的稀疏矩阵 int[][] arr = new int[row][col]

(3)再读取三元组顺序表后几行的数据,并赋给原始的稀疏矩阵

3、代码实现

public class SparseArray {//假设二维数组中一维数组的长度一致

    //二维数组转稀疏数组
    public static int[][] dyadicToSparse(int[][] dyadicArray) {
        int sum = 0;//二维数组非0数据个数
        for (int i = 0; i < dyadicArray.length; i++) {
            for (int j = 0; j < dyadicArray[i].length; j++) {
                if (dyadicArray[i][j] != 0) {
                    sum++;
                }
            }
        }
        int[][] sparseArray = new int[sum + 1][3];
        sparseArray[0][0] = dyadicArray.length;//二维数组行数
        sparseArray[0][1] = dyadicArray[0].length;//二维数组列数
        sparseArray[0][2] = sum;//记录非0数据个数
        int count = 0;//记录是第几个非0数据
        for (int i = 0; i < dyadicArray.length; i++) {
            for (int j = 0; j < dyadicArray.length; j++) {
                if (dyadicArray[i][j] != 0) {
                    count++;
                    sparseArray[count][0] = i;//非0数据的所在行
                    sparseArray[count][1] = j;//非0数据所在列
                    sparseArray[count][2] = dyadicArray[i][j];//非0数据的值
                }
            }
        }
        return sparseArray;
    }

    //稀疏数组转二维数组
    public static int[][] sparseToDyadic(int[][] sparseArray) {
        int dyadicArray[][] = new int[sparseArray[0][0]][sparseArray[0][1]];
        for (int i = 1; i < sparseArray.length; i++) {
            dyadicArray[sparseArray[i][0]][sparseArray[i][1]] = sparseArray[i][2];
        }
        return dyadicArray;
    }
}

 

行逻辑链接的顺序表(压缩存储稀疏矩阵)

1、三元组顺序表每次提取指定元素都需要遍历整个数组,运行效率很低

2、行逻辑链接的顺序表在三元组顺序表的基础上提高了查找某一行非 0 数据的效率

(1)行逻辑链接的顺序表和三元组顺序表的实现过程类似,它们存储矩阵的过程完全相同,都是将矩阵中非 0 元素的三元组(行标、列标和元素值)存储在一维数组中

(2)但为了提高提取查找指定行非 0 元素的效率,前者在存储矩阵时比后者多使用了一个数组,专门记录矩阵中每行第一个非 0 元素在一维数组(三元组)中的位置

3、稀疏矩阵示意图

(1)将矩阵中的非 0 元素采用三元组的形式存储到一维数组 data 中(和三元组顺序表一样)

(2)使用数组 rpos(假设索引从 1 开始)记录矩阵中每行第一个非 0 元素在一维数组(三元顺序表)中的存储位置

(3)rpos[i] == j,表示矩阵第 i 行第一个非 0 元素在三元顺序表中的下标为 j

4、若查找矩阵中第 2 行所有的非 0 元素

(1)如果使用三元组顺序表,就必须从头遍历数组中的每个三元组,逐个进行判断

(2)如果使用行逻辑链接的顺序表,借助 rpos 数组可以直接获得数组第 2 行首个非 0 元素在数组中的位置,还可以获得第 2 行最后一个元素在数组中的位置,查找效率大大提升

 

十字链表(压缩存储稀疏矩阵)

1、对于压缩存储稀疏矩阵,无论是使用三元组顺序表,还是使用行逻辑链接的顺序表,归根结底是使用数组存储稀疏矩阵

2、介于数组“不利于插入和删除数据”的特点,以上两种压缩存储方式都不适合解决类似“向矩阵中添加或删除非 0 元素”的问题

3、例如,A 和 B 分别为两个矩阵,在实现“将矩阵 B 加到矩阵 A 上”的操作时,矩阵 A 中的元素会发生很大的变化,之前的非 0 元素可能变为 0,而 0 元素也可能变为非 0 元素。对于此操作的实现,之前所学的压缩存储方法就显得力不从心

4、存储方式采用的是“链表 + 数组”结构

(1)使用十字链表压缩存储稀疏矩阵时,矩阵中各行各列的元素都用一条链表存储,与此同时,将所有行链表的表头存储到一个数组(rhead),将所有列链表的表头存储到另一个数组(chead)中

(2)两个指针域分别指向所在行的下一个元素和所在列的下一个元素

posted @   半条咸鱼  阅读(102)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示