二维数组与稀疏数组之间的转换

二维,数组,稀疏,之间,转换 · 浏览次数 : 15

小编点评

**内容生成步骤** 1. 创建棋盘数据。 2. 将棋盘数据转换为稀疏数组。 3. 将稀疏数组保存到本地文件。 4. 加载持久化文件中的稀疏数组。 5. 解析数据并绘制成二维图形。 6. 打印内容。 **代码实现** ```java // 创建棋盘数据 int[][] chessArr1 = new int[11][11]; // 将棋盘数据转换为稀疏数组 int[][] sparseArr = towDimenToSparse(chessArr1); // 保存稀疏数组到本地文件 sparseToFile(sparseArr, "稀疏数据.txt"); // 加载持久化文件中的稀疏数组 int[][] sparses = fileToSparse("稀疏数据.txt"); // 解析数据并绘制成二维图形 showTowDimenArr(sparses); ``` **其他** * 在保存稀疏数组之前,可以先将数据缓存到内存中。 * 在解析稀疏数组之前,可以先将数据缓存到内存中。 * 可以根据需要修改代码中的数据类型。

正文

JAVA实现二维数组与稀疏数组之间的转换

一、什么是稀疏数组?

稀疏数组(Sparse array) ,所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀疏数组的内容。

二、稀疏数组应用场景

基本使用场景介绍:当一个数组中大部分元素为0,或者为同一个值的数组时,可以使用稀疏数组来保存该数组。

举例:假设你需要用程序记录如下一张11*11的棋盘,其中用数字1代表白子,数字2代表黑子。我们可以很明显想到用二维数组去存储棋盘数据。

image-20230325093430211

使用二维数组存储如上数据的缺点:

int[][] chessArr1 = new int[11][11];

使用二维数组我们需要创建一个占用11*11*4字节的内存空间去存储,而就这张棋盘数据来看,实际对我们有用的数据只有4*4个字节内存空间,很明显,这极大的浪费了内存空间。于是我们就引出了使用稀疏数组的存储方式去存储如上棋盘数据。

稀疏数据的记录方式:

  1. 稀疏数组第一行记录数组一共有几行几列以及共有多少个需要记录的数据
  2. 把有值位置的行、列对应的值都记录起来,只记录有下子的位置,从而节约内存空间。

image-20230325100450697

从上述结果看来,使用稀疏数组记录棋盘数据,仅仅只需要5*3*4个字节的内存空间。

三、实现思路

①二维数组转稀疏数组的思路及方法实现

思路:

  1. 遍历整个二维数组,获取有效值的个数,记录为sum

  2. 通过sum确定稀疏数组的长度,并创建稀疏数组

    int[][] sparsArr = new int[sum + 1][3];
    
  3. 获取二维数组的行列数和有效值数,赋值给稀疏数组的第一行

  4. 然后再次遍历整个稀疏数组,获取有效值的位置和值,赋值给稀疏数组。

代码实现:

/**
 * 实现将二维数组转换为稀疏数组
 *
 * @param towDimen 传入的二维数组
 * @return 返回的稀疏数组
 */
public int[][] towDimenToSparse(int[][] towDimen) {

    int sum = 0;    // 用于记录有效值的个数

    // 遍历整个二维数组,获取有效值的个数
    for (int[] row : towDimen) {
        for (int data : row) {
            if (data != 0) sum++;
        }
    }

    // 根据获取的有效值个数,确定需要创建的稀疏数组的大小
    int[][] sparsArr = new int[sum + 1][3];

    sparsArr[0][0] = towDimen.length;   // 获取二维数组的行数,赋值给稀疏数组的首行首位
    sparsArr[0][1] = towDimen[0].length;    // 获取二维数组的列数,赋值给稀疏数组的首行次位
    sparsArr[0][2] = sum;   // 将有效值的个数赋值给稀疏数组的首行末位

    int count = 0;  // 记录每次遍历到的有效值所在稀疏数组内的行号
    // 遍历整个二维数组,将每个有效值记录到稀疏数组当中
    for (int i = 0; i < towDimen.length; i++) {
        for (int j = 0; j < towDimen[0].length; j++) {
            if (towDimen[i][j] != 0) {
                count++;
                sparsArr[count][0] = i;
                sparsArr[count][1] = j;
                sparsArr[count][2] = towDimen[i][j];
            }
        }

    }

    return sparsArr;
}

②稀疏数组转二维数组的思路及方法实现

思路:

  1. 通过传入的稀疏数组首行首位以及首行次位的记录来确定二维数组的长宽,并创建二维数组
  2. 继续读取后面的值,根据行列值对应的映射关系,填充到二维数组中。

代码实现:

/**
 * 实现将稀疏数组转换为二维数组
 *
 * @param sparseArr 传入的稀疏二维数组
 * @return 由传入的稀疏数组转换而来的二维数组
 */
public int[][] sparseToTowDimen(int[][] sparseArr) {

    // 通过传入的稀疏数组首行首位以及首行次位的记录来确定二维数组的长宽,并创建二维数组
    int[][] towDimenArr = new int[sparseArr[0][0]][sparseArr[0][1]];

    // 遍历稀疏数组的其余行,还原二维数组
    for (int i = 1; i < sparseArr.length; i++) {
        towDimenArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
    }

    return towDimenArr;
}

③以行列式形式打印显示二维数组

为方便我们后续测试代码,定义以行列式形式打印显示二维数组的方法实现如下

代码实现:

/**
 * 以行列式形式打印显示二维数组
 *
 * @param towDimenArr 传入待显示的二维数组
 */
public void showTowDimenArr(int[][] towDimenArr) {

    for (int[] row : towDimenArr) {
        for (int col : row) {
            System.out.print(col + "\t\t");
        }
        System.out.println();
    }

}

四、代码测试

①测试代码

package com.zhao.test;

import org.junit.Test;

/**
 * ClassName: SparseArray
 * Package: com.zhao.test
 * Description:
 *
 * @Author XH-zhao
 * @Create 2023/3/23 21:19
 * @Version 1.0
 */
public class SparseArray {

    /**
     * 实现将二维数组转换为稀疏数组
     *
     * @param towDimen 传入的二维数组
     * @return 返回的稀疏数组
     */
    public int[][] towDimenToSparse(int[][] towDimen) {

        int sum = 0;    // 用于记录有效值的个数

        // 遍历整个二维数组,获取有效值的个数
        for (int[] row : towDimen) {
            for (int data : row) {
                if (data != 0) sum++;
            }
        }

        // 根据获取的有效值个数,确定需要创建的稀疏数组的大小
        int[][] sparsArr = new int[sum + 1][3];

        sparsArr[0][0] = towDimen.length;   // 获取二维数组的行数,赋值给稀疏数组的首行首位
        sparsArr[0][1] = towDimen[0].length;    // 获取二维数组的列数,赋值给稀疏数组的首行次位
        sparsArr[0][2] = sum;   // 将有效值的个数赋值给稀疏数组的首行末位

        int count = 0;  // 记录每次遍历到的有效值所在稀疏数组内的行号
        // 遍历整个二维数组,将每个有效值记录到稀疏数组当中
        for (int i = 0; i < towDimen.length; i++) {
            for (int j = 0; j < towDimen[0].length; j++) {
                if (towDimen[i][j] != 0) {
                    count++;
                    sparsArr[count][0] = i;
                    sparsArr[count][1] = j;
                    sparsArr[count][2] = towDimen[i][j];
                }
            }

        }

        return sparsArr;
    }

    /**
     * 实现将稀疏数组转换为二维数组
     *
     * @param sparseArr 传入的稀疏二维数组
     * @return 由传入的稀疏数组转换而来的二维数组
     */
    public int[][] sparseToTowDimen(int[][] sparseArr) {

        // 通过传入的稀疏数组首行首位以及首行次位的记录来确定二维数组的长宽,并创建二维数组
        int[][] towDimenArr = new int[sparseArr[0][0]][sparseArr[0][1]];

        // 遍历稀疏数组的其余行,还原二维数组
        for (int i = 1; i < sparseArr.length; i++) {
            towDimenArr[sparseArr[i][0]][sparseArr[i][1]] = sparseArr[i][2];
        }

        return towDimenArr;
    }

    /**
     * 以行列式形式打印显示二维数组
     *
     * @param towDimenArr 传入待显示的二维数组
     */
    public void showTowDimenArr(int[][] towDimenArr) {

        for (int[] row : towDimenArr) {
            for (int col : row) {
                System.out.print(col + "\t\t");
            }
            System.out.println();
        }

    }

    @Test
    public void test01() {

        // 创建棋盘
        int[][] chessArr1 = new int[11][11];
        chessArr1[1][2] = 1;
        chessArr1[2][3] = 2;
        chessArr1[9][10] = 1;
        chessArr1[7][10] = 2;

        System.out.println("二维数组转稀疏数组:");

        int[][] sparseArr = towDimenToSparse(chessArr1);

        showTowDimenArr(sparseArr);

        System.out.println("稀疏数组转二维数组:");

        int[][] towDimen = sparseToTowDimen(sparseArr);

        showTowDimenArr(towDimen);

    }

}

②测试结果

image-20230325121942224

可以看到,上述结果已经成功实现了稀疏数组与二维数组之间的互转!

番外:稀疏数组<-->持久化文件

①将稀疏数组持久化到本地文件

代码实现

/**
 * 把稀疏数据保存为文件
 * @param sparses 要持久化的稀疏数组
 * @param path 持久化到本地的文件路径
 */
public static void sparseToFile(int[][] sparses, String path){
    FileWriter fileWriter = null;
    try {
        File file = new File(path);
        if (file.exists()) {  //存在
            file.delete();  //则删除
        }
        //目录不存在 则创建
        if (!file.getParentFile().exists()) {
            boolean mkdir = file.getParentFile().mkdirs();
            if (!mkdir) {
                throw new RuntimeException("创建目标文件所在目录失败!");
            }
        }
        file.createNewFile();

        fileWriter = new FileWriter(path);
        for (int[] row : sparses) {
            for (int item : row) {
                fileWriter.write(item+"\t");
            }
            //\r\n即为换行
            fileWriter.write("\r\n");
        }
        // 把缓存区内容压入文件
        fileWriter.flush();
        System.out.println("稀疏数据保存文件成功!");
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if(fileWriter!=null){
            try {
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

测试结果

②加载持久化的稀疏数组文件到内存中

代码实现

public static  int[][] fileToSparse(String path){
    File file = new File(path);
    if(!file.exists()){
        System.out.println("文件转稀疏数据失败,文件不能为空!");
        return null;
    }
    BufferedReader bufferedReader = null;
    try {
        bufferedReader = new BufferedReader(new FileReader(file));
 
        String line = null;
        //缓存文件里面的值,再解析处理
        StringBuilder  sb = new StringBuilder ();
        int count = 0;
        while((line = bufferedReader.readLine())!=null){
            //System.out.println("行:"+line);
            sb.append(line+"\r\n");
            count+=1;
        }
        //解析sb数据
        int sparses[][]=new int[count][3];
        String[] splits = sb.toString().split("\r\n");
        //第一行记录的是 二维数据的行和列,有效数据长度,不为有效数据
       for (int i = 0; i < splits.length; i++) {
                String[] temp = splits[i].split("\t");
                for(int j=0;j<temp.length;j++){
                    sparses[i][j] = Integer.parseInt(temp[j]);
                }
        }
       return sparses;
    } catch (Exception e) {
        e.printStackTrace();
    }finally {
        if(bufferedReader!=null){
            try {
                bufferedReader.close();
                bufferedReader = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}

测试结果

image-20230325140836058

成功从持久化文件中加载到内存当中!

与二维数组与稀疏数组之间的转换相似的内容:

二维数组与稀疏数组之间的转换

JAVA实现二维数组与稀疏数组之间的转换 一、什么是稀疏数组? 稀疏数组(Sparse array) ,所谓稀疏数组就是数组中大部分的内容值都未被使用(或都为零),在数组中仅有少部分的空间使用。因此造成内存空间的浪费,为了节省内存空间,并且不影响数组中原有的内容值,我们可以采用一种压缩的方式来表示稀

NumPy 数组排序、过滤与随机数生成详解

本文介绍了NumPy中的数组排序和过滤功能。`np.sort()`函数用于对数组进行升序排序,对二维数组则按行排序。示例展示了如何对一维和二维数组排序。此外,还讲解了使用布尔索引来过滤数组,以及直接在条件中操作数组以创建过滤后的数组。最后,介绍了NumPy的随机数生成,包括整数、浮点数及特定分布的随...

5.6 汇编语言:汇编高效数组寻址

汇编语言是一种面向机器的低级语言,用于编写计算机程序。汇编语言与计算机机器语言非常接近,汇编语言程序可以使用符号、助记符等来代替机器语言的二进制码,但最终会被汇编器编译成计算机可执行的机器码。数组和指针都是用来处理内存地址的操作,二者在C语言中可以互换使用。数组是相同数据类型的一组集合,这些数据在内存中是连续存储的,在C语言中可以定义一维、二维、甚至多维数组。多维数组在内存中也是连续存储的,只是数

#Powerquery 数据结构基础 一维数据与二维数据

本文参考了采悟老师的文章,推荐大家看原文,本文为笔记随笔 https://mp.weixin.qq.com/s?__biz=MzA4MzQwMjY4MA==&mid=2484068871&idx=1&sn=4ab596602ed0a4c851755673d8fcf37a&chksm=8e0c48d0

聊聊神经网络的基础知识

来自《深度学习入门:基于Python的理论与实现》 张量 Numpy、TensorFlow、Pytorch等框架主要是为了计算张量或是基于张量计算。 标量:0阶张量;12,4,3, 向量:一阶张量;[12,4,3] 矩阵:二阶张量;[ [12,4,3], [11,2,3] ] 多阶张量:多维数组;

C#堆排序算法

前言 堆排序是一种高效的排序算法,基于二叉堆数据结构实现。它具有稳定性、时间复杂度为O(nlogn)和空间复杂度为O(1)的特点。 堆排序实现原理 构建最大堆:将待排序数组构建成一个最大堆,即满足父节点大于等于子节点的特性。 将堆顶元素与最后一个元素交换:将最大堆的堆顶元素与堆中的最后一个元素交换位

研发三维GIS系统笔记/实现wgs84投影-001

1. 工作内容,改造引擎,支持wgs84投影 改造原因:目前投影是墨卡托投影(与Google Map一致) 目前的GIS系统是二维的采用这个坐标系是没有问题的 但不支持wgs84瓦片数据以及高程数据,工作中很多数据是wgs84格式的,尤其很多三维GIS都是采用wgs84投影 wgs84 与merca

二八轮动策略:基础与改进

更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流。 二八轮动策略原理 二八轮动策略,通俗的来讲就是大小盘股的轮动策略。 其中“二”代表数量占比20%左右的大盘权重股,“八”代表数量占比80%左右的中小盘股票。如果我们仔细观察股市,经常会看到这样的现象,市场

#Powerbi 10分钟,理解 Rankx 排名函数

一:本文思维导图及示例数据图 1.1思维导图 1.2 示例数据图 二:度量值示例 2.1 函数简介 RANKX 首先为的每一行计值表达式,将结果临时存储为一个值列表。然后在当前筛选上下文中计值,将得到的结果与列表中的值进行比较,根据排名规则和的设置,返回最终排名。 2.2 产品排名(稠密)度量值 这

[转帖]jmeter 使用beanshell 编写脚本

目录 一、介绍 1.1 介绍 1.2 下载&启动 二、jmeter中创建beanshell脚本 三、jmeter与beanshell 数据交互 3.1 例子1 beanshell 将变量传给jmeter 3.2 例子二 jmeter 接收beanshell 生成的变量 四、jmeter中Beansh